--- /dev/null
+# 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/build @marek-safar
+mcs/class @marek-safar
+mcs/errors @marek-safar
+mcs/mcs @marek-safar
+mcs/tests @marek-safar
+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
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
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
=======
public ProcessStartInfo StartInfo { get; set; }
public Stopwatch Stopwatch { get; set; } = new Stopwatch ();
public int? ExitCode { get; set; }
- public StringBuilder StandardOutput { get; set; } = new StringBuilder ();
- public StringBuilder StandardError { get; set; } = new StringBuilder ();
+ public string StandardOutput { get; set; }
+ public string StandardError { get; set; }
}
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);
+ static readonly TimeSpan _timeout = TimeSpan.FromHours (10);
+
+ static readonly Dictionary<string, Action<TestResult>> _processors = new Dictionary<string, Action<TestResult>> () {
+ { "msbiology", Process32BitOutOfMemory },
+ };
static string FilterInvalidXmlChars (string text) {
return Regex.Replace (text, @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]", string.Empty);
}
+ static void Process32BitOutOfMemory (TestResult result)
+ {
+ if (Environment.Is64BitProcess)
+ return;
+
+ if (result.ExitCode == null || result.ExitCode == 0)
+ return;
+
+ if (result.StandardError.Contains ("OutOfMemoryException"))
+ result.ExitCode = 0;
+ }
+
static int Main ()
{
var depDir = Path.Combine ("..", "external", "benchmarker");
for (var i = 0; i < benchmarks.Length; i++) {
var bench = benchmarks [i];
- var sampleFreq = rand.Next (0, 1001);
- var sampleMode = rand.Next (0, 2) == 1 ? "real" : "process";
+ var sampleFreq = rand.Next (-1000, 1001);
+ var sampleMode = rand.Next (0, 2) == 1 ? "-real" : string.Empty;
var maxSamples = rand.Next (0, cpus * 2000 + 1);
- var heapShotFreq = rand.Next (0, 11);
+ var heapShotFreq = rand.Next (-10, 11);
var maxFrames = rand.Next (0, 33);
var options = _options.ToDictionary (x => x, _ => rand.Next (0, 2) == 1)
.Select (x => (x.Value ? string.Empty : "no") + x.Key)
.ToArray ();
- var profOptions = $"sample={sampleFreq},sampling-{sampleMode},maxsamples={maxSamples},heapshot={heapShotFreq}gc,maxframes={maxFrames},{string.Join (",", options)},output=/dev/null";
+ var profOptions = $"maxframes={maxFrames},{string.Join (",", options)},output=/dev/null";
+
+ if (sampleFreq > 0)
+ profOptions += $",sample{sampleMode}={sampleFreq},maxsamples={maxSamples}";
+
+ if (heapShotFreq > 0)
+ profOptions += $",heapshot={heapShotFreq}gc";
var info = new ProcessStartInfo {
UseShellExecute = false,
using (var proc = new Process ()) {
proc.StartInfo = info;
+ var stdout = new StringBuilder ();
+ var stderr = new StringBuilder ();
+
proc.OutputDataReceived += (sender, args) => {
if (args.Data != null)
- result.StandardOutput.AppendLine (args.Data);
+ stdout.AppendLine (args.Data);
};
proc.ErrorDataReceived += (sender, args) => {
if (args.Data != null)
- result.StandardError.AppendLine (args.Data);
+ stderr.AppendLine (args.Data);
};
result.Stopwatch.Start ();
result.ExitCode = proc.ExitCode;
result.Stopwatch.Stop ();
+
+ result.StandardOutput = stdout.ToString ();
+ result.StandardError = stderr.ToString ();
}
var resultStr = result.ExitCode == null ? "timed out" : $"exited with code: {result.ExitCode}";
Console.WriteLine ("===== stdout =====");
Console.ResetColor ();
- Console.WriteLine (result.StandardOutput.ToString ());
+ Console.WriteLine (result.StandardOutput);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine ("===== stderr =====");
Console.ResetColor ();
- Console.WriteLine (result.StandardError.ToString ());
+ Console.WriteLine (result.StandardError);
}
+ if (_processors.TryGetValue (bench.Name, out var processor))
+ processor (result);
+
results.Add (result);
}
writer.WriteStartElement ("failure");
writer.WriteStartElement ("message");
- writer.WriteCData (FilterInvalidXmlChars (result.StandardOutput.ToString ()));
+ writer.WriteCData (FilterInvalidXmlChars (result.StandardOutput));
writer.WriteEndElement ();
writer.WriteStartElement ("stack-trace");
- writer.WriteCData (FilterInvalidXmlChars (result.StandardError.ToString ()));
+ writer.WriteCData (FilterInvalidXmlChars (result.StandardError));
writer.WriteEndElement ();
writer.WriteEndElement ();
AC_ARG_WITH(testing_aot_hybrid, [ --with-testing_aot_hybrid=yes,no If you want to build the testing_aot_hybrid assemblies (defaults to no)], [], [with_testing_aot_hybrid=default])
AC_ARG_WITH(testing_aot_full, [ --with-testing_aot_full=yes,no If you want to build the testing_aot_full assemblies (defaults to no)], [], [with_testing_aot_full=default])
AC_ARG_WITH(winaot, [ --with-winaot=yes,no If you want to build the Windows friendly AOT assemblies (defaults to no)], [], [with_winaot=default])
-AC_ARG_WITH(orbis, [ --with-orbis=yes,no If you want to build the Orbis assemblies (defaults to no)], [], [with_orbis=default])
+AC_ARG_WITH(orbis, [ --with-orbis=yes,no If you want to build the Orbis assemblies (defaults to no)], [], [with_orbis=default])
+AC_ARG_WITH(unreal, [ --with-unreal=yes,no If you want to build the Unreal assemblies (defaults to no)], [], [with_unreal=default])
-AC_ARG_WITH(runtime_preset, [ --with-runtime_preset=net_4_x,all,aot,hybridaot,fullaot,bitcode Which default profile to build (defaults to net_4_x)], [], [with_runtime_preset=net_4_x])
+AC_ARG_WITH(runtime_preset, [ --with-runtime_preset=net_4_x,all,aot,hybridaot,fullaot,bitcode,unreal Which default profile to build (defaults to net_4_x)], [], [with_runtime_preset=net_4_x])
dnl
dnl Profile defaults
with_testing_aot_full_default=no
with_winaot_default=no
with_orbis_default=no
+with_unreal_default=no
with_bitcode_default=no
with_cooperative_gc_default=no
with_xammac_default=yes
with_winaot_default=yes
with_orbis_default=yes
+ with_unreal_default=yes
elif test x$with_runtime_preset = xfullaot; then
DISABLE_MCS_DOCS_default=yes
with_testing_aot_full_default=yes
AOT_BUILD_FLAGS="--runtime=mobile --aot=full,$INVARIANT_AOT_OPTIONS"
AOT_RUN_FLAGS="--runtime=mobile --full-aot"
+elif test x$with_runtime_preset = xunreal; then
+ DISABLE_MCS_DOCS_default=yes
+ with_unreal_default=yes
+ TEST_PROFILE=unreal
+
+ mono_feature_disable_com='yes'
+ mono_feature_disable_remoting='yes'
+ mono_feature_disable_appdomains='no'
+
+ AOT_BUILD_FLAGS="--runtime=mobile --aot=hybrid,$INVARIANT_AOT_OPTIONS"
+ AOT_RUN_FLAGS="--runtime=mobile --hybrid-aot"
else
with_profile4_x_default=yes
fi
if test "x$with_orbis" = "xdefault"; then
with_orbis=$with_orbis_default
fi
+if test "x$with_unreal" = "xdefault"; then
+ with_unreal=$with_unreal_default
+fi
AM_CONDITIONAL(INSTALL_4_x, [test "x$with_profile4_x" = "xyes"])
AM_CONDITIONAL(INSTALL_TESTING_AOT_FULL, [test "x$with_testing_aot_full" != "xno"])
AM_CONDITIONAL(INSTALL_WINAOT, [test "x$with_winaot" != "xno"])
AM_CONDITIONAL(INSTALL_ORBIS, [test "x$with_orbis" != "xno"])
+AM_CONDITIONAL(INSTALL_UNREAL, [test "x$with_unreal" != "xno"])
AM_CONDITIONAL(FULL_AOT_TESTS, [test "x$TEST_PROFILE" = "xtesting_aot_full"] || [test "x$TEST_PROFILE" = "xwinaot"] || [test "x$TEST_PROFILE" = "xorbis"])
-AM_CONDITIONAL(HYBRID_AOT_TESTS, [test "x$TEST_PROFILE" = "xtesting_aot_hybrid"])
+AM_CONDITIONAL(HYBRID_AOT_TESTS, [test "x$TEST_PROFILE" = "xtesting_aot_hybrid"] || [test "x$TEST_PROFILE" = "xunreal"])
default_profile=net_4_x
if test -z "$INSTALL_MONODROID_TRUE"; then :
if test -z "$INSTALL_ORBIS_TRUE"; then :
default_profile=orbis
fi
+if test -z "$INSTALL_UNREAL_TRUE"; then :
+ default_profile=unreal
+fi
if test -z "$INSTALL_4_x_TRUE"; then :
default_profile=net_4_x
fi
AC_SUBST(BOEHM_DEFINES)
fi
+AM_CONDITIONAL(SUPPORT_NULLGC, test "x$libgc" = "xnone")
dnl
dnl End of Boehm GC Configuration
AC_CHECK_HEADERS(pthread.h)
AC_CHECK_HEADERS(pthread_np.h)
AC_CHECK_FUNCS(pthread_mutex_timedlock)
- AC_CHECK_FUNCS(pthread_getattr_np pthread_attr_get_np pthread_setname_np)
+ AC_CHECK_FUNCS(pthread_getattr_np pthread_attr_get_np pthread_setname_np pthread_cond_timedwait_relative_np)
AC_CHECK_FUNCS(pthread_kill)
AC_MSG_CHECKING(for PTHREAD_MUTEX_RECURSIVE)
AC_TRY_COMPILE([ #include <pthread.h>], [
AC_DEFINE(SIZEOF_REGISTER,SIZEOF_VOID_P,[size of machine integer registers])
fi
+AC_SUBST(SIZEOF_VOID_P,[$ac_cv_sizeof_void_p])
+
if test "x$target_byte_order" = "xG_BIG_ENDIAN"; then
AC_DEFINE(TARGET_BYTE_ORDER,G_BIG_ENDIAN,[byte order of target])
elif test "x$target_byte_order" = "xG_LITTLE_ENDIAN"; then
Xamarin.Mac: $with_xammac
Windows AOT: $with_winaot
Orbis: $with_orbis
+ Unreal: $with_unreal
Test profiles: AOT Full ($with_testing_aot_full), AOT Hybrid ($with_testing_aot_hybrid)
JNI support: $jdk_headers_found
libgdiplus: $libgdiplus_msg
-Subproject commit fd9e7e3ba7848fedf4a5e6a3bb08d91de8f9df32
+Subproject commit 1cd7cc5a141a737ee717505923c08d28f5f63c3d
-Subproject commit dab16db1ba42b153098d4e3fe28f2a00861b6863
+Subproject commit 4ae08e8dd6425fa0936aa43d95966539359b5081
-Subproject commit e9e1fb251df4be19b142f0cef2c7dcc13b84f2f2
+Subproject commit 797f074e49933b5fffb42d1a945270f3a88de042
/* 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,
xbuild_14_SUBDIRS := build class tools/xbuild
winaot_SUBDIRS := build class
orbis_SUBDIRS := build class
+unreal_SUBDIRS := build class
include build/rules.make
$(_boot_:%=profile-do--testing_aot_full--%): profile-do--testing_aot_full--%: profile-do--build--%
$(_boot_:%=profile-do--winaot--%): profile-do--winaot--%: profile-do--build--%
$(_boot_:%=profile-do--orbis--%): profile-do--orbis--%: profile-do--build--%
+$(_boot_:%=profile-do--unreal--%): profile-do--unreal--%: profile-do--build--%
$(_boot_:%=profile-do--build--%): profile-do--build--%: profile-do--basic--%
testcorlib:
--- /dev/null
+#! -*- makefile -*-
+
+BOOTSTRAP_PROFILE = build
+
+BOOTSTRAP_MCS = MONO_PATH="$(topdir)/class/lib/$(BOOTSTRAP_PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(INTERNAL_CSC)
+MCS = $(BOOTSTRAP_MCS)
+
+profile-check:
+ @:
+
+DEFAULT_REFERENCES = -r:$(topdir)/class/lib/$(PROFILE)/mscorlib.dll
+
+PROFILE_MCS_FLAGS = \
+ -d:NET_1_1 \
+ -d:NET_2_0 \
+ -d:NET_2_1 \
+ -d:MOBILE \
+ -d:MOBILE_DYNAMIC \
+ -d:NET_3_5 \
+ -d:NET_4_0 \
+ -d:NET_4_5 \
+ -d:MONO \
+ -nowarn:1699 \
+ -nostdlib \
+ $(DEFAULT_REFERENCES) \
+ $(PLATFORM_DEBUG_FLAGS)
+
+FRAMEWORK_VERSION = 2.1
+
+NO_INSTALL = yes
+MOBILE_DYNAMIC = yes
+MOBILE_PROFILE = yes
+NO_CONSOLE = yes
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 =
ifndef EMBEDDED_DRAWING_DEP
# profiles which build a System.Drawing.dll in the repo
-REPO_DRAWING_DEP := $(filter net_4_x orbis winaot, $(PROFILE))
+REPO_DRAWING_DEP := $(filter net_4_x orbis winaot unreal, $(PROFILE))
ifdef REPO_DRAWING_DEP
LIB_REFS += System.Drawing
endif
# profiles which build a System.Drawing.dll in the repo
-REPO_DRAWING_DEP := $(filter net_4_x orbis winaot, $(PROFILE))
+REPO_DRAWING_DEP := $(filter net_4_x orbis winaot unreal, $(PROFILE))
ifdef REPO_DRAWING_DEP
LIB_REFS += System.Drawing
orbis_SUBDIRS = $(common_DEPS_SUBDIRS) $(netstandard_drawing_SUBDIRS) $(mobile_only_DEPS_SUBDIRS)
orbis_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(mobile_only_SUBDIRS)
+unreal_SUBDIRS = $(common_DEPS_SUBDIRS) $(netstandard_drawing_SUBDIRS) $(mobile_only_DEPS_SUBDIRS)
+unreal_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(mobile_only_SUBDIRS)
+
mobile_only_SUBDIRS = System.Net.Ping System.Runtime.Serialization.Formatters System.Security.Cryptography.Csp System.Security.Cryptography.Pkcs \
System.Security.Cryptography.Cng System.Runtime.Loader System.Xml.XPath.XmlDocument System.Reflection.DispatchProxy
System.Drawing \
$(pcl_facade_dirs)
+unreal_dirs := \
+ $(mobile_common_dirs) \
+ System.Drawing \
+ $(pcl_facade_dirs)
+
xammac_4_5_dirs := \
corlib \
Mono.Security \
xbuild_14_SUBDIRS := $(xbuild_4_0_dirs) Microsoft.NuGet.Build.Tasks
winaot_SUBDIRS := $(winaot_dirs)
orbis_SUBDIRS := $(orbis_dirs)
+unreal_SUBDIRS := $(unreal_dirs)
include ../build/rules.make
-SUBDIRS = $(testing_aot_full_dirs) $(testing_aot_hybrid_dirs) $(monotouch_dirs) $(monodroid_dirs) $(xammac_dirs) $(net_4_x_dirs) $(net_4_x_parallel_dirs) $(xammac_net_4_5_SUBDIRS)
+SUBDIRS = $(testing_aot_full_dirs) $(testing_aot_hybrid_dirs) $(monotouch_dirs) $(monodroid_dirs) $(xammac_dirs) $(net_4_x_dirs) $(net_4_x_parallel_dirs) $(xammac_net_4_5_SUBDIRS) $(unreal_dirs)
DIST_ONLY_SUBDIRS = dlr aot-compiler reference-assemblies $(xbuild_4_0_dirs) Microsoft.NuGet.Build.Tasks
var bm = new BuildManager ();
bm.BeginBuild (new BuildParameters () { Loggers = new ILogger [] {new ConsoleLogger (LoggerVerbosity.Diagnostic, TextWriter.Null.WriteLine, null, null)} });
DateTime waitDone = DateTime.MinValue;
- DateTime beforeExec = DateTime.Now;
+ DateTime beforeExec = DateTime.UtcNow;
var l = new List<BuildSubmission> ();
for (int i = 0; i < 10; i++) {
var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" }));
l.Add (sub);
- sub.ExecuteAsync (delegate { waitDone = DateTime.Now; }, null);
+ sub.ExecuteAsync (delegate { waitDone = DateTime.UtcNow; }, null);
}
bm.EndBuild ();
Assert.IsTrue (l.All (s => s.BuildResult.OverallResult == BuildResultCode.Success), "#1");
- DateTime endBuildDone = DateTime.Now;
- Assert.IsTrue (endBuildDone - beforeExec >= TimeSpan.FromSeconds (1), "#2");
- Assert.IsTrue (endBuildDone > waitDone, "#3");
+ DateTime endBuildDone = DateTime.UtcNow;
+ AssertHelper.GreaterOrEqual (endBuildDone - beforeExec, TimeSpan.FromSeconds (1), "#2");
+ AssertHelper.Greater (endBuildDone, waitDone, "#3");
}
[Test]
[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.Now;
+ 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.Now; }, null);
+ sub.ExecuteAsync (cb => waitDone = sw.Elapsed, null);
bm.EndBuild ();
- Assert.IsTrue (sub.BuildResult.OverallResult == BuildResultCode.Success, "#1");
- DateTime endBuildDone = DateTime.Now;
- Assert.IsTrue (endBuildDone - beforeExec >= TimeSpan.FromSeconds (1), "#2");
- Assert.IsTrue (waitDone >= beforeExec, "#3");
- Assert.IsTrue (endBuildDone >= waitDone, "#4");
+ Assert.AreEqual (BuildResultCode.Success, sub.BuildResult.OverallResult, "#1");
+ 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]
<Compile Include="..\..\mcs\settings.cs" />\r
<Compile Include="..\..\mcs\statement.cs" />\r
<Compile Include="..\..\mcs\support.cs" />\r
+ <Compile Include="..\..\mcs\tuples.cs" />\r
<Compile Include="..\..\mcs\typemanager.cs" />\r
<Compile Include="..\..\mcs\typespec.cs" />\r
<Compile Include="..\..\mcs\visit.cs" />\r
../../mcs/support.cs
../../mcs/typemanager.cs
../../mcs/typespec.cs
+../../mcs/tuples.cs
../../mcs/visit.cs
../../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
../../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
_pool = pool;\r
_client = client;\r
_stream = new BufferedStream (client.GetStream());\r
- _controlTime = DateTime.Now;\r
+ _controlTime = DateTime.UtcNow;\r
_buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];\r
}\r
\r
{\r
lock (_pool)\r
{\r
- entry.ControlTime = DateTime.Now; // Initialize timeout\r
+ entry.ControlTime = DateTime.UtcNow; // Initialize timeout\r
_pool.Add (entry);\r
Monitor.Pulse (_pool);\r
}\r
for (int n=0; n < _pool.Count; n++)\r
{\r
UnixConnection entry = (UnixConnection)_pool[n];\r
- if ( (DateTime.Now - entry.ControlTime).TotalSeconds > UnixConnectionPool.KeepAliveSeconds)\r
+ if ( (DateTime.UtcNow - entry.ControlTime).TotalSeconds > UnixConnectionPool.KeepAliveSeconds)\r
{\r
CancelConnection (entry);\r
_pool.RemoveAt(n);\r
using NUnit.Framework;
using System;
+using System.Diagnostics;
using System.Text;
using System.Threading;
using Mono.Unix;
static Thread CreateWaitSignalThread (UnixSignal signal, int timeout)
{
Thread t1 = new Thread(delegate() {
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
bool r = signal.WaitOne (timeout, false);
- DateTime end = DateTime.Now;
+ sw.Stop ();
Assert.AreEqual (signal.Count, 1);
Assert.AreEqual (r, true);
- if ((end - start) > new TimeSpan (0, 0, timeout/1000))
+ if (sw.Elapsed > new TimeSpan (0, 0, timeout/1000))
throw new InvalidOperationException ("Signal slept too long");
});
return t1;
{
Thread t1 = new Thread (delegate () {
using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
bool r = a.WaitOne (5000, false);
- DateTime end = DateTime.Now;
+ sw.Stop ();
Assert.AreEqual (a.Count, 1);
Assert.AreEqual (r, true);
- if ((end - start) > new TimeSpan (0, 0, 5))
+ if (sw.Elapsed > new TimeSpan (0, 0, 5))
throw new InvalidOperationException ("Signal slept too long");
}
});
{
Thread t1 = new Thread (delegate () {
using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
int idx = UnixSignal.WaitAny (new UnixSignal[]{a}, 5000);
- DateTime end = DateTime.Now;
+ sw.Stop ();
Assert.AreEqual (idx, 0);
Assert.AreEqual (a.Count, 1);
- if ((end - start) > new TimeSpan (0, 0, 5))
+ if (sw.Elapsed > new TimeSpan (0, 0, 5))
throw new InvalidOperationException ("Signal slept too long");
}
});
Thread t1 = new Thread (delegate () {
using (UnixSignal a = new UnixSignal (Signum.SIGINT))
using (UnixSignal b = new UnixSignal (Signum.SIGTERM)) {
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
int idx = UnixSignal.WaitAny (new UnixSignal[]{a, b}, 5000);
- DateTime end = DateTime.Now;
+ sw.Stop ();
Assert.AreEqual (idx, 1);
Assert.AreEqual (a.Count, 0);
Assert.AreEqual (b.Count, 1);
- if ((end - start) > new TimeSpan (0, 0, 5))
+ if (sw.Elapsed > new TimeSpan (0, 0, 5))
throw new InvalidOperationException ("Signal slept too long");
}
});
public void TestNoEmit ()
{
using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
bool r = u.WaitOne (5100, false);
Assert.AreEqual (r, false);
- DateTime end = DateTime.Now;
- if ((end - start) < new TimeSpan (0, 0, 5))
- throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + (end-start).ToString());
+ sw.Stop ();
+ if (sw.Elapsed < new TimeSpan (0, 0, 5))
+ throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + sw.Elapsed.TotalSeconds.ToString());
}
}
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
Heap = 6,
Sample = 7,
Runtime = 8,
- Coverage = 9,
Meta = 10,
AllocationNoBacktrace = 0 << 4,
RuntimeJitHelper = 1 << 4,
- CoverageAssembly = 0 << 4,
- CoverageMethod = 1 << 4,
- CoverageStatement = 2 << 4,
- CoverageClass = 3 << 4,
-
MetaSynchronizationPoint = 0 << 4,
}
ExceptionHandling = 10,
}
- // mono/profiler/log.h : SAMPLE_*
- public enum LogSampleHitType {
- Cycles = 1,
- Instructions = 2,
- CacheMisses = 3,
- CacheHits = 4,
- Branches = 5,
- BranchMisses = 6,
- }
-
- // mono/metadata/profiler.h : MonoProfileGCRootType
+ // mono/metadata/profiler.h : MonoProfilerGCRootType
[Flags]
public enum LogHeapRootAttributes {
Pinning = 1 << 8,
TypeMask = 0xff,
}
- // mono/metadata/profiler.h : MonoProfilerMonitorEvent
+ // mono/profiler/log.h : MonoProfilerMonitorEvent
public enum LogMonitorEvent {
Contention = 1,
Done = 2,
Fault = 4,
}
- // mono/metadata/profiler.h : MonoGCEvent
+ // 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,
}
- // mono/sgen/gc-internal-agnostic.h : GCHandleType
+ // mono/metadata/mono-gc.h : MonoGCHandleType
public enum LogGCHandleType {
Weak = 0,
WeakTrackResurrection = 1,
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,
+ }
}
{
}
- public virtual void Visit (AssemblyCoverageEvent ev)
- {
- }
-
- public virtual void Visit (ClassCoverageEvent ev)
- {
- }
-
- public virtual void Visit (MethodCoverageEvent ev)
- {
- }
-
- public virtual void Visit (StatementCoverageEvent ev)
- {
- }
-
public virtual void Visit (SynchronizationPointEvent ev)
{
}
public sealed class SampleHitEvent : LogEvent {
- public LogSampleHitType Type { get; internal set; }
-
public long ThreadId { get; internal set; }
public IReadOnlyList<long> UnmanagedBacktrace { get; internal set; }
}
}
- public sealed class AssemblyCoverageEvent : LogEvent {
-
- public string AssemblyName { get; internal set; }
-
- public Guid Guid { get; internal set; }
-
- public string FileName { get; internal set; }
-
- public long NumberOfMethods { get; internal set; }
-
- public long FullyCovered { get; internal set; }
-
- public long PartiallyCovered { get; internal set; }
-
- internal override void Accept (LogEventVisitor visitor)
- {
- visitor.Visit (this);
- }
- }
-
- public sealed class ClassCoverageEvent : LogEvent {
-
- public string AssemblyName { get; internal set; }
-
- public string ClassName { get; internal set; }
-
- public long NumberOfMethods { get; internal set; }
-
- public long FullyCovered { get; internal set; }
-
- public long PartiallyCovered { get; internal set; }
-
- internal override void Accept (LogEventVisitor visitor)
- {
- visitor.Visit (this);
- }
- }
-
- public sealed class MethodCoverageEvent : LogEvent {
-
- public string AssemblyName { get; internal set; }
-
- public string ClassName { get; internal set; }
-
- public string MethodName { get; internal set; }
-
- public string MethodSignature { get; internal set; }
-
- public string FileName { get; internal set; }
-
- public ulong MetadataToken { get; internal set; }
-
- public long MethodId { get; internal set; }
-
- public long NumberOfStatements { get; internal set; }
-
- internal override void Accept (LogEventVisitor visitor)
- {
- visitor.Visit (this);
- }
- }
-
- public sealed class StatementCoverageEvent : LogEvent {
-
- public long MethodId { get; internal set; }
-
- public long RelativeILOffset { get; internal set; }
-
- public ulong Counter { get; internal set; }
-
- public long Line { get; internal set; }
-
- public long Column { get; internal set; }
-
- internal override void Accept (LogEventVisitor visitor)
- {
- visitor.Visit (this);
- }
- }
-
public sealed class SynchronizationPointEvent : LogEvent {
public LogSynchronizationPoint Type { get; internal set; }
switch (extType) {
case LogEventType.SampleHit:
return new SampleHitEvent {
- Type = (LogSampleHitType) Reader.ReadByte (),
ThreadId = ReadPointer (),
UnmanagedBacktrace = ReadBacktrace (true, false),
ManagedBacktrace = ReadBacktrace (true),
default:
throw new LogException ($"Invalid extended event type ({extType}).");
}
- case LogEventType.Coverage:
- switch (extType) {
- case LogEventType.CoverageAssembly:
- return new AssemblyCoverageEvent {
- AssemblyName = Reader.ReadCString (),
- Guid = Guid.Parse (Reader.ReadCString ()),
- FileName = Reader.ReadCString (),
- NumberOfMethods = (long) Reader.ReadULeb128 (),
- FullyCovered = (long) Reader.ReadULeb128 (),
- PartiallyCovered = (long) Reader.ReadULeb128 (),
- };
- case LogEventType.CoverageMethod:
- return new MethodCoverageEvent {
- AssemblyName = Reader.ReadCString (),
- ClassName = Reader.ReadCString (),
- MethodName = Reader.ReadCString (),
- MethodSignature = Reader.ReadCString (),
- FileName = Reader.ReadCString (),
- MetadataToken = Reader.ReadULeb128 (),
- MethodId = (long) Reader.ReadULeb128 (),
- NumberOfStatements = (long) Reader.ReadULeb128 (),
- };
- case LogEventType.CoverageStatement:
- return new StatementCoverageEvent {
- MethodId = (long) Reader.ReadULeb128 (),
- RelativeILOffset = (long) Reader.ReadULeb128 (),
- Counter = Reader.ReadULeb128 (),
- Line = (long) Reader.ReadULeb128 (),
- Column = (long) Reader.ReadULeb128 (),
- };
- case LogEventType.CoverageClass:
- return new ClassCoverageEvent {
- AssemblyName = Reader.ReadCString (),
- ClassName = Reader.ReadCString (),
- NumberOfMethods = (long) Reader.ReadULeb128 (),
- FullyCovered = (long) Reader.ReadULeb128 (),
- PartiallyCovered = (long) Reader.ReadULeb128 (),
- };
- default:
- throw new LogException ($"Invalid extended event type ({extType}).");
- }
case LogEventType.Meta:
switch (extType) {
case LogEventType.MetaSynchronizationPoint:
long ReadObject ()
{
- return Reader.ReadSLeb128 () + _bufferHeader.ObjectBase;
+ return Reader.ReadSLeb128 () + _bufferHeader.ObjectBase << 3;
}
long ReadMethod ()
--- /dev/null
+// 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); }
+ }
+ }
+}
+++ /dev/null
-// 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.
- }
-}
using System.IO;
using System.Net;
using System.Net.Security;
+using System.Threading;
using System.Threading.Tasks;
using SSA = System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
void EndWrite (IAsyncResult asyncResult);
+ Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken);
+
Task ShutdownAsync ();
TransportContext TransportContext {
--- /dev/null
+#include common_System.Core.dll.sources
+#include dynamic_System.Core.dll.sources
+
+System.Security.Cryptography/AesCryptoServiceProvider.cs
+System.Security.Cryptography/AesTransform.cs
+System.Security.Cryptography/MD5Cng.cs
+System.Security.Cryptography/SHA1Cng.cs
+System.Security.Cryptography/SHA256Cng.cs
+System.Security.Cryptography/SHA384Cng.cs
+System.Security.Cryptography/SHA512Cng.cs
+
+../referencesource/System.Core/System/Security/Cryptography/AesManaged.cs
+../referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs
+../referencesource/System.Core/System/Security/Cryptography/ECKeyXmlFormat.cs
--- /dev/null
+#include mobile_System.Data.dll.sources
namespace MonoTests.System.DirectoryServices \r
{\r
[TestFixture]\r
- [Category ("InetAccess")]\r
public class DirectoryServicesDirectoryEntryTest\r
{\r
#region Fields\r
{\r
de = null;\r
configuration = new TestConfiguration ();\r
+\r
+ if (String.IsNullOrEmpty (configuration.ConnectionString))\r
+ Assert.Ignore ("No configuration");\r
}\r
\r
\r
namespace MonoTests.System.DirectoryServices \r
{\r
[TestFixture]\r
- [Category ("InetAccess")]\r
public class DirectoryServicesDirectorySearcherTest\r
{\r
#region Fields\r
{\r
de = null; \r
configuration = new TestConfiguration ();\r
+\r
+ if (String.IsNullOrEmpty (configuration.ConnectionString))\r
+ Assert.Ignore ("No configuration");\r
}\r
\r
\r
namespace MonoTests.System.DirectoryServices \r
{\r
[TestFixture]\r
- [Category ("InetAccess")]\r
public class DirectoryServicesSearchResultTest\r
{\r
#region Fields\r
{\r
de = null;\r
configuration = new TestConfiguration ();\r
+\r
+ if (String.IsNullOrEmpty (configuration.ConnectionString))\r
+ Assert.Ignore ("No configuration");\r
}\r
\r
\r
RESX_RESOURCE_STRING = ../../../external/corefx/src/System.Drawing.Common/src/Resources/Strings.resx
-ifeq (winaot, $(PROFILE))
-LIB_MCS_FLAGS += /keyfile:../msfinal.pub
-else ifeq (orbis, $(PROFILE))
+MOBILE_LIKE := $(filter winaot orbis unreal, $(PROFILE))
+
+ifdef MOBILE_LIKE
LIB_MCS_FLAGS += /keyfile:../msfinal.pub
else
LIB_MCS_FLAGS += -d:FEATURE_TYPECONVERTER,SUPPORTS_WINDOWS_COLORS
<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
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\NativeMethods.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\Duplex.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\InvalidPrinterException.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\InvalidPrinterException.Serializable.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\Margins.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\Margins.Serializable.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PaperKinds.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PaperSize.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PaperSize.Serializable.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PaperSource.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PaperSource.Serializable.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PaperSourceKind.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PreviewPageInfo.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrintAction.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrinterResolution.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrinterResolution.Serializable.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrinterResolutionKind.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrinterUnit.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Printing\PrinterUnitConvert.cs" />\r
public PrivateFontCollection ()
{
- Status status = GDIPlus.GdipNewPrivateFontCollection (out nativeFontCollection);
+ Status status = GDIPlus.GdipNewPrivateFontCollection (out _nativeFontCollection);
GDIPlus.CheckStatus (status);
}
throw new FileNotFoundException ();
// note: MS throw the same exception FileNotFoundException if the file exists but isn't a valid font file
- Status status = GDIPlus.GdipPrivateAddFontFile (nativeFontCollection, fname);
+ Status status = GDIPlus.GdipPrivateAddFontFile (_nativeFontCollection, fname);
GDIPlus.CheckStatus (status);
}
public void AddMemoryFont (IntPtr memory, int length)
{
// note: MS throw FileNotFoundException if something is bad with the data (except for a null pointer)
- Status status = GDIPlus.GdipPrivateAddMemoryFont (nativeFontCollection, memory, length);
+ Status status = GDIPlus.GdipPrivateAddMemoryFont (_nativeFontCollection, memory, length);
GDIPlus.CheckStatus (status);
}
// methods
protected override void Dispose (bool disposing)
{
- if (nativeFontCollection!=IntPtr.Zero) {
- GDIPlus.GdipDeletePrivateFontCollection (ref nativeFontCollection);
+ if (_nativeFontCollection!=IntPtr.Zero) {
+ GDIPlus.GdipDeletePrivateFontCollection (ref _nativeFontCollection);
// This must be zeroed out, otherwise our base will also call
// the GDI+ delete method on unix platforms. We're keeping the
// base.Dispose() call in case other cleanup ever gets added there
- nativeFontCollection = IntPtr.Zero;
+ _nativeFontCollection = IntPtr.Zero;
}
base.Dispose (disposing);
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
../../../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
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/Duplex.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/InvalidPrinterException.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/InvalidPrinterException.Serializable.cs
System.Drawing.Printing/MarginsConverter.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/Margins.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/Margins.Serializable.cs
System.Drawing.Printing/PrintingServices.cs
System.Drawing.Printing/PrintingServicesWin32.cs
System.Drawing.Printing/PrintingServicesUnix.cs
System.Drawing.Printing/PageSettings.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PaperKinds.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PaperSize.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PaperSize.Serializable.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PaperSource.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PaperSource.Serializable.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PaperSourceKind.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PreviewPageInfo.cs
System.Drawing.Printing/PreviewPrintController.cs
System.Drawing.Printing/PrintController.cs
System.Drawing.Printing/PrintDocument.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrinterResolution.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrinterResolution.Serializable.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrinterResolutionKind.cs
System.Drawing.Printing/PrinterSettings.cs
../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Printing/PrinterUnit.cs
public FontFamily (string name, FontCollection fontCollection)
{
- IntPtr handle = (fontCollection == null) ? IntPtr.Zero : fontCollection.nativeFontCollection;
+ IntPtr handle = (fontCollection == null) ? IntPtr.Zero : fontCollection._nativeFontCollection;
Status status = GDIPlus.GdipCreateFontFamilyFromName (name, handle, out nativeFontFamily);
GDIPlus.CheckStatus (status);
}
--- /dev/null
+#include mobile_System.IdentityModel.dll.sources
wrequest.ResendContentFactory = content.CopyTo;
- var stream = await wrequest.GetRequestStreamAsync ().ConfigureAwait (false);
- await request.Content.CopyToAsync (stream).ConfigureAwait (false);
+ using (var stream = await wrequest.GetRequestStreamAsync ().ConfigureAwait (false)) {
+ await request.Content.CopyToAsync (stream).ConfigureAwait (false);
+ }
} else if (HttpMethod.Post.Equals (request.Method) || HttpMethod.Put.Equals (request.Method) || HttpMethod.Delete.Equals (request.Method)) {
// Explicitly set this to make sure we're sending a "Content-Length: 0" header.
// This fixes the issue that's been reported on the forums:
<ItemGroup>\r
<Compile Include="..\..\build\common\Consts.cs" />\r
<Compile Include="..\..\build\common\MonoTODOAttribute.cs" />\r
+ <Compile Include="..\referencesource\System.Net\net\IPEndPointCollection.cs" />\r
<Compile Include="Assembly\AssemblyInfo.cs" />\r
- <Compile Include="Assembly\TypeForwarders.cs" />\r
- <Compile Include="System.Net\IPEndPointCollection.cs" />\r </ItemGroup>\r
+ <Compile Include="Assembly\TypeForwarders.cs" />\r </ItemGroup>\r
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
Other similar extension points exist, see Microsoft.Common.targets.\r
<Target Name="BeforeBuild">\r
+++ /dev/null
-//
-// System.Net.NetworkInformation.NetworkChange
-//
-// Author:
-// Gonzalo Paniagua Javier (gonzalo@novell.com)
-//
-// Copyright (c) 2006, 2009 Novell, Inc. (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-#if MOBILE
-using System.Runtime.InteropServices;
-
-namespace System.Net.NetworkInformation {
- public abstract class NetworkChange {
- internal delegate void NetworkStateChangedCallback (IntPtr sender, IntPtr data);
- static NetworkChange ()
- {
- state_changed_callback = new NetworkStateChangedCallback (StateChangedCallback);
- _moonlight_cbinding_moon_network_service_set_network_state_changed_callback (_moonlight_cbinding_runtime_get_network_service(),
- state_changed_callback,
- IntPtr.Zero);
- }
-
- static NetworkStateChangedCallback state_changed_callback;
-
- static void StateChangedCallback (IntPtr sender, IntPtr data)
- {
- try {
- NetworkAddressChangedEventHandler h = NetworkAddressChanged;
- if (h != null)
- h (null, EventArgs.Empty);
- } catch (Exception ex) {
- try {
- Console.WriteLine ("Unhandled exception: {0}", ex);
- } catch {
- // Ignore
- }
- }
- }
-
- protected NetworkChange ()
- {
- }
-
- public static event NetworkAddressChangedEventHandler NetworkAddressChanged;
-
- [DllImport ("moon")]
- internal extern static IntPtr _moonlight_cbinding_runtime_get_network_service ();
-
- [DllImport ("moon")]
- internal extern static void _moonlight_cbinding_moon_network_service_set_network_state_changed_callback (IntPtr service,
- NetworkStateChangedCallback handler, IntPtr data);
-
- [DllImport ("moon")]
- internal extern static bool _moonlight_cbinding_moon_network_service_get_is_network_available (IntPtr service);
- }
-}
-#endif
-
+++ /dev/null
-//
-// System.Net.NetworkInformation.NetworkInterface
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@novell.com)
-// Atsushi Enomoto (atsushi@ximian.com)
-// Miguel de Icaza (miguel@novell.com)
-// Eric Butler (eric@extremeboredom.net)
-// Marek Habersack (mhabersack@novell.com)
-//
-// Copyright (c) 2006-2009 Novell, Inc. (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.NetworkInformation {
-
- public abstract class NetworkInterface {
-
- protected NetworkInterface ()
- {
- }
-
- public static bool GetIsNetworkAvailable ()
- {
- return NetworkChange._moonlight_cbinding_moon_network_service_get_is_network_available (NetworkChange._moonlight_cbinding_runtime_get_network_service ());
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// BaseDomainPolicy.cs
-//
-// Authors:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-// Base class for shared stuff between the Silverlight and Flash policies
-// e.g. Headers and Domain comparison
-
-namespace System.Net.Policy {
-
- abstract class BaseDomainPolicy : ICrossDomainPolicy {
-
- static string root;
- static Uri app;
-#if !TEST
- static BaseDomainPolicy ()
- {
- ApplicationUri = new Uri (AppDomain.CurrentDomain.GetData ("xap_uri") as string);
- }
-#endif
- static public Uri ApplicationUri {
- get { return app; }
- set {
- app = value;
- root = null;
- }
- }
-
- static public string ApplicationRoot {
- get {
- if (root == null)
- root = CrossDomainPolicyManager.GetRoot (ApplicationUri);
- return root;
- }
- }
-
- public class Headers {
-
- sealed class PrefixComparer : IEqualityComparer<string> {
-
- public bool Equals (string x, string y)
- {
- int check_length = x.Length - 1;
- if ((x.Length > 0) && (x [check_length] == '*'))
- return (String.Compare (x, 0, y, 0, check_length, StringComparison.OrdinalIgnoreCase) == 0);
-
- return (String.Compare (x, y, StringComparison.OrdinalIgnoreCase) == 0);
- }
-
- public int GetHashCode (string obj)
- {
- return (obj == null) ? 0 : obj.GetHashCode ();
- }
- }
-
- static PrefixComparer pc = new PrefixComparer ();
-
- private List<string> list;
-
- public Headers ()
- {
- }
-
- public bool AllowAllHeaders { get; private set; }
-
- public bool IsAllowed (string[] headers)
- {
- if (AllowAllHeaders)
- return true;
-
- if (headers == null || headers.Length == 0)
- return true;
-
- return headers.All (s => list.Contains (s, pc));
- }
-
- public void SetHeaders (string raw)
- {
- if (raw == "*") {
- AllowAllHeaders = true;
- list = null;
- } else if (raw != null) {
- string [] headers = raw.Split (',');
- list = new List<string> (headers.Length + 1);
- list.Add ("Content-Type");
- for (int i = 0; i < headers.Length; i++) {
- string s = headers [i].Trim ();
- if (!String.IsNullOrEmpty (s))
- list.Add (s);
- }
- } else {
- // without a specified 'http-request-headers' no header, expect Content-Type, is allowed
- AllowAllHeaders = false;
- list = new List<string> (1);
- list.Add ("Content-Type");
- }
- }
- }
-
- abstract public bool IsAllowed (WebRequest request);
-
- public Exception Exception {
- get; internal set;
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// ClientAccessPolicy.cs
-//
-// Authors:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace System.Net.Policy {
-
- partial class ClientAccessPolicy : BaseDomainPolicy {
-
- public class AccessPolicy {
-
- public const short MinPort = 4502;
- public const short MaxPort = 4534;
-
- public List<AllowFrom> AllowedServices { get; private set; }
- public List<GrantTo> GrantedResources { get; private set; }
- public long PortMask { get; set; }
-
- public AccessPolicy ()
- {
- AllowedServices = new List<AllowFrom> ();
- GrantedResources = new List<GrantTo> ();
- }
-
- public bool PortAllowed (int port)
- {
- if ((port < MinPort) || (port > MaxPort))
- return false;
-
- return (((PortMask >> (port - MinPort)) & 1) == 1);
- }
- }
-
- public ClientAccessPolicy ()
- {
- AccessPolicyList = new List<AccessPolicy> ();
- }
-
- public List<AccessPolicy> AccessPolicyList { get; private set; }
-
- public bool IsAllowed (IPEndPoint endpoint)
- {
- foreach (AccessPolicy policy in AccessPolicyList) {
- // does something allow our URI in this policy ?
- foreach (AllowFrom af in policy.AllowedServices) {
- // fake "GET" as method as this does not apply to sockets
- if (af.IsAllowed (ApplicationUri, "GET")) {
- // if so, is our request port allowed ?
- if (policy.PortAllowed (endpoint.Port))
- return true;
- }
- }
- }
- // no policy allows this socket connection
- return false;
- }
-
- // note: tests show that it only applies to Silverlight policy (seems to work with Flash)
- // and only if we're not granting full access (i.e. '/' with all subpaths)
- // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=466043
- private bool CheckOriginalPath (Uri uri)
- {
- // Path Restriction for cross-domain requests
- // http://msdn.microsoft.com/en-us/library/cc838250(VS.95).aspx
- string original = uri.OriginalString;
- // applies to the *path* only (not the query part)
- int query = original.IndexOf ('?');
- if (query != -1)
- original = original.Substring (0, query);
-
- if (original.Contains ('%') || original.Contains ("./") || original.Contains ("..")) {
- // special case when no path restriction applies - i.e. the above characters are accepted by SL
- if (AccessPolicyList.Count != 1)
- return false;
- AccessPolicy policy = AccessPolicyList [0];
- if (policy.GrantedResources.Count != 1)
- return false;
- GrantTo gt = policy.GrantedResources [0];
- if (gt.Resources.Count != 1)
- return false;
- Resource r = gt.Resources [0];
- return (r.IncludeSubpaths && (r.Path == "/"));
- }
- return true;
- }
-
- public override bool IsAllowed (WebRequest request)
- {
- return IsAllowed (request.RequestUri, request.Method, request.Headers.AllKeys);
- }
-
- public bool IsAllowed (Uri uri, string method, params string [] headerKeys)
- {
- foreach (AccessPolicy policy in AccessPolicyList) {
- // does something allow our URI in this policy ?
- foreach (AllowFrom af in policy.AllowedServices) {
- // is the application (XAP) URI allowed by the policy ?
- // check headers
- if (!af.HttpRequestHeaders.IsAllowed (headerKeys)) {
- return false;
- }
-
- if (af.IsAllowed (ApplicationUri, method)) {
- foreach (GrantTo gt in policy.GrantedResources) {
- // is the requested access to the Uri granted under this policy ?
- if (gt.IsGranted (uri)) {
- // at this stage the URI has removed the "offending" characters so
- // we need to look at the original
- return CheckOriginalPath (uri);
- }
- }
- }
- }
- }
- // no policy allows this web connection
- return false;
- }
-
- public class AllowFrom {
-
- public AllowFrom ()
- {
- Domains = new List<string> ();
- HttpRequestHeaders = new Headers ();
- }
-
- public bool AllowAnyDomain { get; set; }
-
- public List<string> Domains { get; private set; }
-
- public Headers HttpRequestHeaders { get; private set; }
-
- public bool AllowAnyMethod { get; set; }
-
- public bool IsAllowed (Uri uri, string method)
- {
- // check methods
- if (!AllowAnyMethod) {
- // if not all methods are allowed (*) then only GET and POST request are possible
- // further restriction exists in the Client http stack
- if ((String.Compare (method, "GET", StringComparison.OrdinalIgnoreCase) != 0) &&
- (String.Compare (method, "POST", StringComparison.OrdinalIgnoreCase) != 0)) {
- return false;
- }
- }
-
- // check domains
- if (AllowAnyDomain)
- return true;
-
- if (Domains.All (domain => !CheckDomainUri (uri, domain)))
- return false;
- return true;
- }
-
- const string AllHttpScheme = "http://*";
- const string AllHttpsScheme = "https://*";
- const string AllFileScheme = "file:///";
-
- static bool CheckDomainUri (Uri applicationUri, string policy)
- {
- Uri uri;
- if (Uri.TryCreate (policy, UriKind.Absolute, out uri)) {
- // if no local path is part of the policy domain then we compare to the root
- if (uri.LocalPath == "/")
- return (uri.ToString () == ApplicationRoot);
- // otherwise the path must match
- if (uri.LocalPath != ApplicationUri.LocalPath)
- return false;
- return (CrossDomainPolicyManager.GetRoot (uri) == ApplicationRoot);
- }
-
- // SL policies supports a * wildcard at the start of their host name (but not elsewhere)
-
- // check for matching protocol
- if (!policy.StartsWith (ApplicationUri.Scheme))
- return false;
-
- switch (ApplicationUri.Scheme) {
- case "http":
- if (policy == AllHttpScheme)
- return (applicationUri.Port == 80);
- break;
- case "https":
- if (policy == AllHttpsScheme)
- return (applicationUri.Port == 443);
- break;
- case "file":
- if (policy == AllFileScheme)
- return true;
- break;
- }
-
- if (policy.IndexOf ("://*.", ApplicationUri.Scheme.Length) != ApplicationUri.Scheme.Length)
- return false;
- // remove *. from uri
- policy = policy.Remove (ApplicationUri.Scheme.Length + 3, 2);
- // create Uri - without the *. it should be a valid one
- if (!Uri.TryCreate (policy, UriKind.Absolute, out uri))
- return false;
- // path must be "empty" and query and fragment (really) empty
- if ((uri.LocalPath != "/") || !String.IsNullOrEmpty (uri.Query) || !String.IsNullOrEmpty (uri.Fragment))
- return false;
- // port must match
- if (ApplicationUri.Port != uri.Port)
- return false;
- // the application uri host must end with the policy host name
- return ApplicationUri.DnsSafeHost.EndsWith (uri.DnsSafeHost);
- }
- }
-
- public class GrantTo
- {
- public GrantTo ()
- {
- Resources = new List<Resource> ();
- }
-
- public List<Resource> Resources { get; private set; }
-
- public bool IsGranted (Uri uri)
- {
- foreach (var gr in Resources) {
- if (gr.IncludeSubpaths) {
- string granted = gr.Path;
- string local = uri.LocalPath;
- if (local.StartsWith (granted, StringComparison.Ordinal)) {
- // "/test" equals "/test" and "test/xyx" but not "/test2"
- // "/test/" equals "test/xyx" but not "/test" or "/test2"
- if (local.Length == granted.Length)
- return true;
- else if (granted [granted.Length - 1] == '/')
- return true;
- else if (local [granted.Length] == '/')
- return true;
- }
- } else {
- if (uri.LocalPath == gr.Path)
- return true;
- }
- }
- return false;
- }
- }
-
- public class Resource {
- private string path;
-
- public string Path {
- get { return path; }
- set {
- // an empty Path Ressource makes the *whole* policy file invalid
- if (String.IsNullOrEmpty (value))
- throw new NotSupportedException ();
- path = value;
- }
- }
-
- public bool IncludeSubpaths { get; set; }
- }
- }
-}
-
-#endif
-
-
+++ /dev/null
-//
-// ClientAccessPolicyParser.cs
-//
-// Authors:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Xml;
-
-/*
-default namespace = ""
-
-grammar {
-
-start = access-policy
-
-access-policy = element access-policy {
- element cross-domain-access {
- element policy { allow-from, grant-to }
- }
-}
-
-allow-from = element allow-from {
- attribute http-request-headers { text },
- element domain {
- attribute uri { text }
- }
-}
-
-grant-to = element grant-to {
- (resource | socket-resource)+
-}
-
-resource = element resource {
- attribute path { text },
- attribute include-subpaths { "true" | "false" }
-}
-
-socket-resource = element socket-resource {
- attribute port { text },
- attribute protocol { text }
-}
-
-}
-*/
-
-namespace System.Net.Policy {
-
- partial class ClientAccessPolicy {
-
- static bool IsNonElement (XmlReader reader)
- {
- return (reader.NodeType != XmlNodeType.Element);
- }
-
- static bool IsNonEmptyElement (XmlReader reader)
- {
- return (reader.IsEmptyElement || IsNonElement (reader));
- }
-
- static public ICrossDomainPolicy FromStream (Stream stream)
- {
- ClientAccessPolicy cap = new ClientAccessPolicy ();
-
- // Silverlight accepts whitespaces before the XML - which is invalid XML
- StreamReader sr = new StreamReader (stream);
- while (Char.IsWhiteSpace ((char) sr.Peek ()))
- sr.Read ();
-
- XmlReaderSettings policy_settings = new XmlReaderSettings ();
- policy_settings.DtdProcessing = DtdProcessing.Ignore;
- using (XmlReader reader = XmlReader.Create (sr, policy_settings)) {
- reader.MoveToContent ();
- if (reader.IsEmptyElement) {
- reader.Skip ();
- return null;
- }
- reader.ReadStartElement ("access-policy", String.Empty);
- for (reader.MoveToContent (); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
- if (IsNonEmptyElement (reader) || (reader.LocalName != "cross-domain-access")) {
- reader.Skip ();
- continue;
- }
-
- reader.ReadStartElement ("cross-domain-access", String.Empty);
- for (reader.MoveToContent (); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
- if (IsNonEmptyElement (reader) || (reader.Name != "policy")) {
- reader.Skip ();
- continue;
- }
-
- ReadPolicyElement (reader, cap);
- }
- reader.ReadEndElement ();
- }
- reader.ReadEndElement ();
- }
- return cap;
- }
-
- static void ReadPolicyElement (XmlReader reader, ClientAccessPolicy cap)
- {
- if (reader.HasAttributes || reader.IsEmptyElement) {
- reader.Skip ();
- return;
- }
-
- var policy = new AccessPolicy ();
- bool valid = true;
-
- reader.ReadStartElement ("policy", String.Empty);
- for (reader.MoveToContent (); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
- if (IsNonElement (reader)) {
- reader.Skip ();
- continue;
- }
-
- switch (reader.LocalName) {
- case "allow-from":
- ReadAllowFromElement (reader, policy);
- break;
- case "grant-to":
- ReadGrantToElement (reader, policy);
- break;
- default:
- valid = false;
- reader.Skip ();
- break;
- }
- }
-
- if (valid)
- cap.AccessPolicyList.Add (policy);
- reader.ReadEndElement ();
- }
-
- static void ReadAllowFromElement (XmlReader reader, AccessPolicy policy)
- {
- if (IsNonEmptyElement (reader)) {
- reader.Skip ();
- return;
- }
-
- bool valid = true;
- string headers = null;
- string methods = null; // new in SL3
- if (reader.HasAttributes) {
- int n = reader.AttributeCount;
- headers = reader.GetAttribute ("http-request-headers");
- if (headers != null)
- n--;
- methods = reader.GetAttribute ("http-methods");
- if (methods != null)
- n--;
- valid = (n == 0);
- }
-
- var v = new AllowFrom ();
- v.HttpRequestHeaders.SetHeaders (headers);
- v.AllowAnyMethod = (methods == "*"); // only legal value defined, otherwise restricted to GET and POST
- reader.ReadStartElement ("allow-from", String.Empty);
- for (reader.MoveToContent (); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
- if (IsNonElement (reader) || !String.IsNullOrEmpty (reader.NamespaceURI)) {
- reader.Skip ();
- continue;
- }
- switch (reader.LocalName) {
- case "domain":
- var d = reader.GetAttribute ("uri");
- if (d == "*")
- v.AllowAnyDomain = true;
- else
- v.Domains.Add (d);
- reader.Skip ();
- break;
- default:
- valid = false;
- reader.Skip ();
- continue;
- }
- }
- if (valid)
- policy.AllowedServices.Add (v);
- reader.ReadEndElement ();
- }
-
- // only "path" and "include-subpaths" attributes are allowed - anything else is not considered
- static Resource CreateResource (XmlReader reader)
- {
- int n = reader.AttributeCount;
- string path = reader.GetAttribute ("path");
- if (path != null)
- n--;
- string subpaths = reader.GetAttribute ("include-subpaths");
- if (subpaths != null)
- n--;
- if ((n != 0) || !reader.IsEmptyElement)
- return null;
-
- return new Resource () {
- Path = path,
- IncludeSubpaths = subpaths == null ? false : XmlConvert.ToBoolean (subpaths)
- };
- }
-
- static void ReadGrantToElement (XmlReader reader, AccessPolicy policy)
- {
- var v = new GrantTo ();
- bool valid = true;
-
- if (reader.HasAttributes || reader.IsEmptyElement) {
- reader.Skip ();
- return;
- }
-
- reader.ReadStartElement ("grant-to", String.Empty);
- for (reader.MoveToContent (); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
- if (IsNonElement (reader) || !String.IsNullOrEmpty (reader.NamespaceURI)) {
- reader.Skip ();
- continue;
- }
-
- switch (reader.LocalName) {
- case "resource":
- var r = CreateResource (reader);
- if (r == null)
- valid = false;
- else
- v.Resources.Add (r);
- break;
- case "socket-resource":
- // ignore everything that is not TCP
- if (reader.GetAttribute ("protocol") != "tcp")
- break;
- // we can merge them all together inside a policy
- policy.PortMask |= ParsePorts (reader.GetAttribute ("port"));
- break;
- default:
- valid = false;
- break;
- }
- reader.Skip ();
- }
- if (valid)
- policy.GrantedResources.Add (v);
- reader.ReadEndElement ();
- }
-
- // e.g. reserved ? 4534-4502
- static long ParsePorts (string ports)
- {
- long mask = 0;
- int sep = ports.IndexOf ('-');
- if (sep >= 0) {
- // range
- ushort from = ParsePort (ports.Substring (0, sep));
- ushort to = ParsePort (ports.Substring (sep + 1));
- for (int port = from; port <= to; port++)
- mask |= (long) (1ul << (port - AccessPolicy.MinPort));
- } else {
- // single
- ushort port = ParsePort (ports);
- mask |= (long) (1ul << (port - AccessPolicy.MinPort));
- }
- return mask;
- }
-
- static ushort ParsePort (string s)
- {
- ushort port;
- if (!UInt16.TryParse (s, out port) || (port < AccessPolicy.MinPort) || (port > AccessPolicy.MaxPort))
- throw new XmlException ("Invalid port");
- return port;
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// CrossDomainPolicyManager.cs
-//
-// Authors:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Security;
-using System.Text;
-using System.Threading;
-
-namespace System.Net.Policy {
-
- internal static class CrossDomainPolicyManager {
-
- public static string GetRoot (Uri uri)
- {
- if ((uri.Scheme == "http" && uri.Port == 80) || (uri.Scheme == "https" && uri.Port == 443) || (uri.Port == -1))
- return String.Format ("{0}://{1}/", uri.Scheme, uri.DnsSafeHost);
- else
- return String.Format ("{0}://{1}:{2}/", uri.Scheme, uri.DnsSafeHost, uri.Port);
- }
-#if !TEST
- public const string ClientAccessPolicyFile = "/clientaccesspolicy.xml";
- public const string CrossDomainFile = "/crossdomain.xml";
-
- const int Timeout = 10000;
-
- // Web Access Policy
-
- static Dictionary<string,ICrossDomainPolicy> policies = new Dictionary<string,ICrossDomainPolicy> ();
-
- static internal ICrossDomainPolicy PolicyDownloadPolicy = new PolicyDownloadPolicy ();
- static ICrossDomainPolicy site_of_origin_policy = new SiteOfOriginPolicy ();
- static ICrossDomainPolicy no_access_policy = new NoAccessPolicy ();
-
- static Uri GetRootUri (Uri uri)
- {
- return new Uri (GetRoot (uri));
- }
-
- public static Uri GetSilverlightPolicyUri (Uri uri)
- {
- return new Uri (GetRootUri (uri), CrossDomainPolicyManager.ClientAccessPolicyFile);
- }
-
- public static Uri GetFlashPolicyUri (Uri uri)
- {
- return new Uri (GetRootUri (uri), CrossDomainPolicyManager.CrossDomainFile);
- }
-
- public static ICrossDomainPolicy GetCachedWebPolicy (Uri uri)
- {
- // if we request an Uri from the same site then we return an "always positive" policy
- if (SiteOfOriginPolicy.HasSameOrigin (uri, BaseDomainPolicy.ApplicationUri))
- return site_of_origin_policy;
-
- // otherwise we search for an already downloaded policy for the web site
- string root = GetRoot (uri);
- ICrossDomainPolicy policy = null;
- policies.TryGetValue (root, out policy);
- // and we return it (if we have it) or null (if we dont)
- return policy;
- }
-
- private static void AddPolicy (Uri responseUri, ICrossDomainPolicy policy)
- {
- string root = GetRoot (responseUri);
- policies [root] = policy;
- }
-
- // see moon/test/2.0/WebPolicies/Pages.xaml.cs for all test cases
- private static bool CheckContentType (string contentType)
- {
- const string application_xml = "application/xml";
-
- // most common case: all text/* are accepted
- if (contentType.StartsWith ("text/"))
- return true;
-
- // special case (e.g. used in nbcolympics)
- if (contentType.StartsWith (application_xml)) {
- if (application_xml.Length == contentType.Length)
- return true; // exact match
-
- // e.g. "application/xml; charset=x" - we do not care what comes after ';'
- if (contentType.Length > application_xml.Length)
- return contentType [application_xml.Length] == ';';
- }
- return false;
- }
-
- public static ICrossDomainPolicy BuildSilverlightPolicy (HttpWebResponse response)
- {
- // return null if no Silverlight policy was found, since we offer a second chance with a flash policy
- if ((response.StatusCode != HttpStatusCode.OK) || !CheckContentType (response.ContentType))
- return null;
-
- ICrossDomainPolicy policy = null;
- try {
- policy = ClientAccessPolicy.FromStream (response.GetResponseStream ());
- if (policy != null)
- AddPolicy (response.ResponseUri, policy);
- } catch (Exception ex) {
- Console.WriteLine (String.Format ("CrossDomainAccessManager caught an exception while reading {0}: {1}",
- response.ResponseUri, ex));
- // and ignore.
- }
- return policy;
- }
-
- public static ICrossDomainPolicy BuildFlashPolicy (HttpWebResponse response)
- {
- ICrossDomainPolicy policy = null;
- if ((response.StatusCode == HttpStatusCode.OK) && CheckContentType (response.ContentType)) {
- try {
- policy = FlashCrossDomainPolicy.FromStream (response.GetResponseStream ());
- } catch (Exception ex) {
- Console.WriteLine (String.Format ("CrossDomainAccessManager caught an exception while reading {0}: {1}",
- response.ResponseUri, ex));
- // and ignore.
- }
- if (policy != null) {
- // see DRT# 864 and 865
- string site_control = response.InternalHeaders ["X-Permitted-Cross-Domain-Policies"];
- if (!String.IsNullOrEmpty (site_control))
- (policy as FlashCrossDomainPolicy).SiteControl = site_control;
- }
- }
-
- // the flash policy was the last chance, keep a NoAccess into the cache
- if (policy == null)
- policy = no_access_policy;
-
- AddPolicy (response.ResponseUri, policy);
- return policy;
- }
-
- // Socket Policy
- //
- // - we connect once to a site for the entire application life time
- // - this returns us a policy file (silverlight format only) or else no access is granted
- // - this policy file
- // - can contain multiple policies
- // - can apply to multiple domains
- // - can grant access to several resources
-
- static Dictionary<string,ClientAccessPolicy> socket_policies = new Dictionary<string,ClientAccessPolicy> ();
- static byte [] socket_policy_file_request = Encoding.UTF8.GetBytes ("<policy-file-request/>");
- const int PolicyPort = 943;
-
- static Stream GetPolicyStream (IPEndPoint endpoint)
- {
- MemoryStream ms = new MemoryStream ();
- ManualResetEvent mre = new ManualResetEvent (false);
- // Silverlight only support TCP
- Socket socket = new Socket (endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
-
- // Application code can't connect to port 943, so we need a special/internal API/ctor to allow this
- SocketAsyncEventArgs saea = new SocketAsyncEventArgs (true);
- saea.RemoteEndPoint = new IPEndPoint (endpoint.Address, PolicyPort);
- saea.Completed += delegate (object sender, SocketAsyncEventArgs e) {
- if (e.SocketError != SocketError.Success) {
- mre.Set ();
- return;
- }
-
- switch (e.LastOperation) {
- case SocketAsyncOperation.Connect:
- e.SetBuffer (socket_policy_file_request, 0, socket_policy_file_request.Length);
- socket.SendAsync (e);
- break;
- case SocketAsyncOperation.Send:
- byte [] buffer = new byte [256];
- e.SetBuffer (buffer, 0, buffer.Length);
- socket.ReceiveAsync (e);
- break;
- case SocketAsyncOperation.Receive:
- int transfer = e.BytesTransferred;
- if (transfer > 0) {
- ms.Write (e.Buffer, 0, transfer);
- // Console.Write (Encoding.UTF8.GetString (e.Buffer, 0, transfer));
- }
-
- if ((transfer == 0) || (transfer < e.Buffer.Length)) {
- ms.Position = 0;
- mre.Set ();
- } else {
- socket.ReceiveAsync (e);
- }
- break;
- }
- };
-
- socket.ConnectAsync (saea);
-
- // behave like there's no policy (no socket access) if we timeout
- if (!mre.WaitOne (Timeout))
- return null;
-
- return ms;
- }
-
- static Stream GetPolicyStream (Uri uri)
- {
- // FIXME
- throw new NotSupportedException ("Fetching socket policy from " + uri.ToString () + " is not yet available in moonlight");
- }
-
- public static ClientAccessPolicy CreateForEndPoint (IPEndPoint endpoint, SocketClientAccessPolicyProtocol protocol)
- {
- Stream s = null;
-
- switch (protocol) {
- case SocketClientAccessPolicyProtocol.Tcp:
- s = GetPolicyStream (endpoint);
- break;
- case SocketClientAccessPolicyProtocol.Http:
- // <quote>It will NOT attempt to download the policy via the custom TCP protocol if the
- // policy check fails.</quote>
- // http://blogs.msdn.com/ncl/archive/2010/04/15/silverlight-4-socket-policy-changes.aspx
- string url = String.Format ("http://{0}:80{1}", endpoint.Address.ToString (),
- CrossDomainPolicyManager.ClientAccessPolicyFile);
- s = GetPolicyStream (new Uri (url));
- break;
- }
-
- if ((s == null) || (s.Length == 0))
- return null;
-
- ClientAccessPolicy policy = null;
- try {
- policy = (ClientAccessPolicy) ClientAccessPolicy.FromStream (s);
- } catch (Exception ex) {
- Console.WriteLine (String.Format ("CrossDomainAccessManager caught an exception while reading {0}: {1}",
- endpoint, ex.Message));
- // and ignore.
- }
-
- return policy;
- }
-
- static public bool CheckEndPoint (EndPoint endpoint, SocketClientAccessPolicyProtocol protocol)
- {
- // if needed transform the DnsEndPoint into a usable IPEndPoint
- IPEndPoint ip = (endpoint as IPEndPoint);
- if (ip == null)
- throw new ArgumentException ("endpoint");
-
- // find the policy (cached or to be downloaded) associated with the endpoint
- string address = ip.Address.ToString ();
- ClientAccessPolicy policy = null;
- if (!socket_policies.TryGetValue (address, out policy)) {
- policy = CreateForEndPoint (ip, protocol);
- socket_policies.Add (address, policy);
- }
-
- // no access granted if no policy is available
- if (policy == null)
- return false;
-
- // does the policy allows access ?
- return policy.IsAllowed (ip);
- }
-#endif
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// FlashCrossDomainPolicy.cs
-//
-// Author:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace System.Net.Policy {
-
- partial class FlashCrossDomainPolicy : BaseDomainPolicy {
-
- private string site_control;
-
- public FlashCrossDomainPolicy ()
- {
- AllowedAccesses = new List<AllowAccessFrom> ();
- AllowedHttpRequestHeaders = new List<AllowHttpRequestHeadersFrom> ();
- }
-
- public List<AllowAccessFrom> AllowedAccesses { get; private set; }
- public List<AllowHttpRequestHeadersFrom> AllowedHttpRequestHeaders { get; private set; }
-
- public string SiteControl {
- get { return String.IsNullOrEmpty (site_control) ? "all" : site_control; }
- set { site_control = value; }
- }
-
- public override bool IsAllowed (WebRequest request)
- {
- return IsAllowed (request.RequestUri, request.Headers.AllKeys);
- }
-
- public bool IsAllowed (Uri uri, string [] headerKeys)
- {
- switch (SiteControl) {
- case "all":
- case "master-only":
- case "by-ftp-filename":
- break;
- default:
- // others, e.g. 'none', are not supported/accepted
- return false;
- }
-
- if (AllowedAccesses.Count > 0 &&
- !AllowedAccesses.Any (a => a.IsAllowed (uri, headerKeys)))
- return false;
- if (AllowedHttpRequestHeaders.Count > 0 &&
- AllowedHttpRequestHeaders.Any (h => h.IsRejected (uri, headerKeys)))
- return false;
-
- return true;
- }
-
- public class AllowAccessFrom {
-
- public AllowAccessFrom ()
- {
- Secure = true; // true by default
- }
-
- public string Domain { get; set; }
- public bool AllowAnyPort { get; set; }
- public int [] ToPorts { get; set; }
- public bool Secure { get; set; }
-
- public bool IsAllowed (Uri uri, string [] headerKeys)
- {
- // "A Flash policy file must allow access to all domains to be used by the Silverlight runtime."
- // http://msdn.microsoft.com/en-us/library/cc645032(VS.95).aspx
- if (Domain != "*")
- return false;
- if (!AllowAnyPort && ToPorts != null && Array.IndexOf (ToPorts, uri.Port) < 0)
- return false;
-
- // if Secure is false then it allows applications from HTTP to download data from HTTPS servers
- if (!Secure)
- return true;
- // if Secure is true then data on HTTPS servers can only be accessed by application on HTTPS servers
- if (uri.Scheme == Uri.UriSchemeHttps)
- return (ApplicationUri.Scheme == Uri.UriSchemeHttps);
- // otherwise FILE/HTTP applications can access HTTP uris
- return true;
- }
- }
-
- public class AllowHttpRequestHeadersFrom {
-
- public AllowHttpRequestHeadersFrom ()
- {
- Headers = new Headers ();
- }
-
- public string Domain { get; set; }
- public bool AllowAllHeaders { get; set; }
- public Headers Headers { get; private set; }
- public bool Secure { get; set; }
-
- public bool IsRejected (Uri uri, string [] headerKeys)
- {
- // "A Flash policy file must allow access to all domains to be used by the Silverlight runtime."
- // http://msdn.microsoft.com/en-us/library/cc645032(VS.95).aspx
- if (Domain != "*")
- return false;
-
- if (Headers.IsAllowed (headerKeys))
- return false;
-
- // if Secure is false then it allows applications from HTTP to download data from HTTPS servers
- if (!Secure)
- return true;
- // if Secure is true then only application on HTTPS servers can access data on HTTPS servers
- if (ApplicationUri.Scheme == Uri.UriSchemeHttps)
- return (uri.Scheme == Uri.UriSchemeHttps);
- // otherwise FILE/HTTP applications can access HTTP uris
- return true;
- }
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// FlashCrossDomainPolicyParser.cs
-//
-// Author:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Xml;
-
-/*
-
-Specification: http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html
-
-# This grammar is based on the xsd from Adobe, but the schema is wrong.
-# It should have used interleave (all). Some crossdomain.xml are invalidated.
-# (For example, try mono-xmltool --validate-xsd http://www.adobe.com/xml/schemas/PolicyFile.xsd http://twitter.com/crossdomain.xml)
-
-default namespace = ""
-
-grammar {
-
-start = cross-domain-policy
-
-cross-domain-policy = element cross-domain-policy {
- element site-control {
- attribute permitted-cross-domain-policies {
- "all" | "by-contract-type" | "by-ftp-filename" | "master-only" | "none"
- }
- }?,
- element allow-access-from {
- attribute domain { text },
- attribute to-ports { text }?,
- attribute secure { xs:boolean }?
- }*,
- element allow-http-request-headers-from {
- attribute domain { text },
- attribute headers { text },
- attribute secure { xs:boolean }?
- }*,
- element allow-access-from-identity {
- element signatory {
- element certificate {
- attribute fingerprint { text },
- attribute fingerprint-algorithm { text }
- }
- }
- }*
-}
-
-}
-
-*/
-
-namespace System.Net.Policy {
-
- partial class FlashCrossDomainPolicy {
-
- static bool ReadBooleanAttribute (string attribute)
- {
- switch (attribute) {
- case null:
- case "true":
- return true;
- case "false":
- return false;
- default:
- throw new XmlException ();
- }
- }
-
- // only "domain" and "secure" attributes are allowed - anything else is considered invalid
- static AllowAccessFrom CreateAllowAccessFrom (XmlReader reader)
- {
- int n = reader.AttributeCount;
- string domain = reader.GetAttribute ("domain");
- if (domain != null)
- n--;
- string secure = reader.GetAttribute ("secure");
- if (secure != null)
- n--;
- if (n != 0)
- throw new XmlException ("unknown/unsupported attributes");
-
- return new AllowAccessFrom () { Domain = domain, Secure = ReadBooleanAttribute (secure) };
- }
-
- // only "domain", "secure" and "headers" attributes are allowed - anything else is considered invalid
- static AllowHttpRequestHeadersFrom CreateAllowHttpRequestHeadersFrom (XmlReader reader)
- {
- int n = reader.AttributeCount;
- string domain = reader.GetAttribute ("domain");
- if (domain != null)
- n--;
- string secure = reader.GetAttribute ("secure");
- if (secure != null)
- n--;
- string headers = reader.GetAttribute ("headers");
- if (headers != null)
- n--;
- if (n != 0)
- throw new XmlException ("unknown/unsupported attributes");
-
- var h = new AllowHttpRequestHeadersFrom () { Domain = domain, Secure = ReadBooleanAttribute (secure) };
- h.Headers.SetHeaders (headers);
- return h;
- }
-
- // only "permitted-cross-domain-policies" attribute is allowed - anything else is considered invalid
- static string GetSiteControl (XmlReader reader)
- {
- int n = reader.AttributeCount;
- string site = reader.GetAttribute ("permitted-cross-domain-policies");
- if (site != null)
- n--;
- if (n != 0)
- throw new XmlException ("unknown/unsupported attributes");
- return site;
- }
-
- static public ICrossDomainPolicy FromStream (Stream stream)
- {
- FlashCrossDomainPolicy cdp = new FlashCrossDomainPolicy ();
-
- // Silverlight accepts whitespaces before the XML - which is invalid XML
- StreamReader sr = new StreamReader (stream);
- while (Char.IsWhiteSpace ((char) sr.Peek ()))
- sr.Read ();
-
- XmlReaderSettings policy_settings = new XmlReaderSettings ();
- policy_settings.DtdProcessing = DtdProcessing.Ignore;
- using (XmlReader reader = XmlReader.Create (sr, policy_settings)) {
-
- reader.MoveToContent ();
- if (reader.HasAttributes || reader.IsEmptyElement) {
- reader.Skip ();
- return null;
- }
-
- while (!reader.EOF) {
- reader.ReadStartElement ("cross-domain-policy", String.Empty);
- for (reader.MoveToContent (); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
- if (reader.NodeType != XmlNodeType.Element) {
- reader.Skip ();
- continue;
- }
-
- switch (reader.LocalName) {
- case "site-control":
- cdp.SiteControl = GetSiteControl (reader);
- reader.Skip ();
- break;
- case "allow-access-from":
- var a = CreateAllowAccessFrom (reader);
- cdp.AllowedAccesses.Add (a);
- reader.Skip ();
- break;
- case "allow-http-request-headers-from":
- var h = CreateAllowHttpRequestHeadersFrom (reader);
- cdp.AllowedHttpRequestHeaders.Add (h);
- reader.Skip ();
- break;
- default:
- reader.Skip ();
- return null;
- }
- }
- reader.ReadEndElement ();
- reader.MoveToContent ();
- }
- }
-
- // if none supplied set a default for headers
- if (cdp.AllowedHttpRequestHeaders.Count == 0) {
- var h = new AllowHttpRequestHeadersFrom () { Domain = "*", Secure = true };
- h.Headers.SetHeaders (null); // defaults
- cdp.AllowedHttpRequestHeaders.Add (h);
- }
- return cdp;
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// System.Windows.Browser.Net.ICrossDomainPolicy interface
-//
-// Contact:
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Policy {
-
- interface ICrossDomainPolicy {
-
- bool IsAllowed (WebRequest request);
-
- Exception Exception { get; }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// System.Windows.Browser.Net.PolicyDownloadPolicy class
-//
-// Contact:
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System.Security;
-
-namespace System.Net.Policy {
-
- sealed class NoAccessPolicy : ICrossDomainPolicy {
-
- static SecurityException security_exception = new SecurityException ();
- static NotSupportedException not_supported_exception = new NotSupportedException ();
-
- Exception ex;
-
- public bool IsAllowed (WebRequest request)
- {
- ex = security_exception;
-
- foreach (string header in request.Headers) {
- if (String.Compare ("Content-Type", header, StringComparison.OrdinalIgnoreCase) != 0)
- ex = not_supported_exception;
- }
- return false;
- }
-
- public Exception Exception {
- get { return ex; }
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// System.Windows.Browser.Net.PolicyDownloadPolicy class
-//
-// Contact:
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Policy {
-
- sealed class PolicyDownloadPolicy : ICrossDomainPolicy {
-
- public bool IsAllowed (WebRequest request)
- {
- return IsLocalPathPolicy (request.RequestUri);
- }
-
- static public bool IsLocalPathPolicy (Uri uri)
- {
- string local = uri.LocalPath;
- if (String.CompareOrdinal (local, CrossDomainPolicyManager.ClientAccessPolicyFile) == 0)
- return true;
- if (String.CompareOrdinal (local, CrossDomainPolicyManager.CrossDomainFile) == 0)
- return true;
-
- return false;
- }
-
- public Exception Exception {
- get { return null; }
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// System.Windows.Browser.Net.SiteOfOriginPolicy class
-//
-// Contact:
-// Moonlight List (moonlight-list@lists.ximian.com)
-//
-// Copyright (C) 2009-2010 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Policy {
-
- sealed class SiteOfOriginPolicy : ICrossDomainPolicy {
-
- public bool IsAllowed (WebRequest request)
- {
- // a WebRequest to the site of origin (SOO) is always granted
- return true;
- }
-
- // helper to determine if two Uri share the same origin (policy wise)
- static public bool HasSameOrigin (Uri a, Uri b)
- {
- return ((a.Scheme == b.Scheme) && (a.DnsSafeHost == b.DnsSafeHost) &&
- ((a.Port == -1) || (b.Port == -1) || (a.Port == b.Port)));
- }
-
- public Exception Exception {
- get { return null; }
- }
- }
-}
-
-#endif
-
+++ /dev/null
-// AddressFamily.cs (Silverlight specific)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Sockets {
-
- public enum AddressFamily {
- Unknown = -1,
- Unspecified = 0,
- InterNetwork = 2,
- InterNetworkV6 = 23,
- }
-}
-
-#endif
-
+++ /dev/null
-// ProtocolType.cs (Silverlight specific)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Sockets {
-
- public enum ProtocolType {
-
- Unknown = -1,
- Unspecified = 0,
- Tcp = 6
- }
-}
-
-#endif
-
+++ /dev/null
-// System.Net.Sockets.SocketAsyncOperation.cs (Silverlight specific)
-//
-// Authors:
-// Marek Habersack (mhabersack@novell.com)
-//
-// Copyright (c) 2008 Novell, Inc. (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-namespace System.Net.Sockets {
- public enum SocketAsyncOperation {
- None,
- Connect = 2,
- Receive = 4,
- Send = 7,
- }
-}
-#endif
+++ /dev/null
-//
-// SocketClientAccessPolicyProtocol.cs (Silverlight specific)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-namespace System.Net.Sockets {
-
- public enum SocketClientAccessPolicyProtocol {
- Tcp,
- Http
- }
-}
-
+++ /dev/null
-//
-// System.Net.Sockets.SocketException
-//
-// Author:
-// Dick Porter <dick@ximian.com>
-//
-// (C) 2002 Ximian, Inc.
-// Copyright (C) 2009 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Runtime.CompilerServices;
-
-namespace System.Net.Sockets {
-
- public class SocketException : Exception {
-
- int error_code;
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private static extern int WSAGetLastError_internal ();
-
- public SocketException ()
- {
- error_code = WSAGetLastError_internal ();
- }
-
- public SocketException (int errorCode)
- {
- error_code = errorCode;
- }
-
- internal SocketException (int error, string message)
- : base (message)
- {
- error_code = error;
- }
-
- public int ErrorCode {
- get { return error_code; }
- }
-
- public SocketError SocketErrorCode {
- get { return (SocketError) error_code; }
- }
- }
-}
+++ /dev/null
-// SocketType.cs (Silverlight specific)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Sockets {
-
- public enum SocketType {
- Unknown = -1,
- Stream = 1,
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// UdpAnySourceMulticastClient (Moonlight 4.0)
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2010 Novell, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Sockets {
-
- [MonoTODO ("stub (with some validations) to allow SL4 tests compilation")]
- public class UdpAnySourceMulticastClient : IDisposable {
-
- const string ObjectDisposed = "UdpAnySourceMulticastClient instance was disposed.";
- bool disposed;
-
- public UdpAnySourceMulticastClient (IPAddress groupAddress, int localPort)
- {
- if (groupAddress == null)
- throw new ArgumentNullException ("groupAddress");
- if ((localPort < 0) || (localPort > 65535))
- throw new ArgumentOutOfRangeException ("localPort");
- if (localPort < 1024)
- throw new SocketException ();
-
- throw new NotImplementedException ();
- }
-
- public bool MulticastLoopback { get; set; }
- public int ReceiveBufferSize { get; set; }
- public int SendBufferSize { get; set; }
-
- public IAsyncResult BeginJoinGroup (AsyncCallback callback, object state)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
-
- // check policy
- //throw new SocketException ((int) SocketError.AccessDenied);
- throw new NotImplementedException ();
- // callback called if join operation is completed
- }
-
- public void EndJoinGroup (IAsyncResult result)
- {
- if (result == null)
- throw new ArgumentNullException ("result");
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
-
- throw new NotImplementedException ();
- }
-
- public IAsyncResult BeginReceiveFromGroup (byte [] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if ((offset < 0) || (offset > buffer.Length))
- throw new ArgumentOutOfRangeException ("offset");
- if ((count < 0) || (count > buffer.Length - offset))
- throw new ArgumentOutOfRangeException ("count");
-
- throw new NotImplementedException ();
- }
-
- public int EndReceiveFromGroup (IAsyncResult result, out IPEndPoint source)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
-
- throw new NotImplementedException ();
- }
-
- public IAsyncResult BeginSendTo (byte [] buffer, int offset, int count, IPEndPoint remoteEndPoint, AsyncCallback callback, object state)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if ((offset < 0) || (offset > buffer.Length))
- throw new ArgumentOutOfRangeException ("offset");
- if ((count < 0) || (count > buffer.Length - offset))
- throw new ArgumentOutOfRangeException ("count");
-
- throw new NotImplementedException ();
- }
-
- public void EndSendTo (IAsyncResult result)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (result == null)
- throw new ArgumentNullException ("result");
-
- throw new NotImplementedException ();
- }
-
- public IAsyncResult BeginSendToGroup (byte [] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if ((offset < 0) || (offset > buffer.Length))
- throw new ArgumentOutOfRangeException ("offset");
- if ((count < 0) || (count > buffer.Length - offset))
- throw new ArgumentOutOfRangeException ("count");
-
- throw new NotImplementedException ();
- }
-
- public void EndSendToGroup (IAsyncResult result)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (result == null)
- throw new ArgumentNullException ("result");
-
- throw new NotImplementedException ();
- }
-
- public void BlockSource (IPAddress sourceAddress)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
-
- throw new NotImplementedException ();
- }
-
- public void UnblockSource (IPAddress sourceAddress)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
-
- throw new NotImplementedException ();
- }
-
- public void Dispose ()
- {
- disposed = true;
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// UdpSingleSourceMulticastClient (Moonlight 4.0)
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2010 Novell, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net.Sockets {
-
- [MonoTODO ("stub (with some validations) to allow SL4 tests compilation")]
- public class UdpSingleSourceMulticastClient : IDisposable {
-
- const string ObjectDisposed = "UdpSingleSourceMulticastClient instance was disposed.";
- bool disposed;
-
- public UdpSingleSourceMulticastClient (IPAddress sourceAddress, IPAddress groupAddress, int localPort)
- {
- if (sourceAddress == null)
- throw new ArgumentNullException ("sourceAddress");
- if (groupAddress == null)
- throw new ArgumentNullException ("groupAddress");
- if ((localPort < 0) || (localPort > 65535))
- throw new ArgumentOutOfRangeException ("localPort");
- if (localPort < 1024)
- throw new SocketException ();
-
- throw new NotImplementedException ();
- }
-
- public int ReceiveBufferSize { get; set; }
- public int SendBufferSize { get; set; }
-
- public IAsyncResult BeginJoinGroup (AsyncCallback callback, object state)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
-
- throw new NotImplementedException ();
- }
-
- public void EndJoinGroup (IAsyncResult result)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
-
- throw new NotImplementedException ();
- }
-
- public IAsyncResult BeginReceiveFromSource (byte [] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if ((offset < 0) || (offset > buffer.Length))
- throw new ArgumentOutOfRangeException ("offset");
- if ((count < 0) || (count > buffer.Length - offset))
- throw new ArgumentOutOfRangeException ("count");
-
- throw new NotImplementedException ();
- }
-
- public int EndReceiveFromSource (IAsyncResult result, out int sourcePort)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (result == null)
- throw new ArgumentNullException ("result");
-
- throw new NotImplementedException ();
- }
-
- public IAsyncResult BeginSendToSource (byte [] buffer, int offset, int count, int remotePort, AsyncCallback callback, object state)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if ((offset < 0) || (offset > buffer.Length))
- throw new ArgumentOutOfRangeException ("offset");
- if ((count < 0) || (count > buffer.Length - offset))
- throw new ArgumentOutOfRangeException ("count");
-
- throw new NotImplementedException ();
- }
-
- public void EndSendToSource (IAsyncResult result)
- {
- if (disposed)
- throw new ObjectDisposedException (ObjectDisposed);
- if (result == null)
- throw new ArgumentNullException ("result");
-
- throw new NotImplementedException ();
- }
-
- public void Dispose ()
- {
- disposed = true;
- }
- }
-}
-
-#endif
-
Assembly/TypeForwarders.cs
../../build/common/Consts.cs
../../build/common/MonoTODOAttribute.cs
-System.Net/IPEndPointCollection.cs
+../referencesource/System.Net/net/IPEndPointCollection.cs
+++ /dev/null
-// System.Net.Dns.cs
-//
-// Author: Mads Pultz (mpultz@diku.dk)
-// Author: Lawrence Pit (loz@cable.a2000.nl)
-//
-// (C) Mads Pultz, 2001
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Collections;
-using System.Net.Sockets;
-using System.Runtime.CompilerServices;
-
-namespace System.Net {
-
- internal static class Dns {
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static bool GetHostByName_internal(string host, out string h_name, out string[] h_aliases, out string[] h_addr_list);
-
- internal static IPAddress [] GetHostAddresses (string hostNameOrAddress)
- {
- if (hostNameOrAddress == null)
- throw new ArgumentNullException ("hostNameOrAddress");
-
- if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0")
- throw new ArgumentException ("Addresses 0.0.0.0 (IPv4) " +
- "and ::0 (IPv6) are unspecified addresses. You " +
- "cannot use them as target address.",
- "hostNameOrAddress");
-
- IPAddress addr;
- if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
- return new IPAddress[1] { addr };
-
- string h_name;
- string[] h_aliases, h_addrlist;
-
- bool ret = GetHostByName_internal (hostNameOrAddress, out h_name, out h_aliases, out h_addrlist);
- if (ret == false)
- throw new SocketException(11001);
-
- IPHostEntry entry = hostent_to_IPHostEntry (h_name, h_aliases, h_addrlist);
- return entry.AddressList;
- }
-
- private static IPHostEntry hostent_to_IPHostEntry(string h_name, string[] h_aliases, string[] h_addrlist)
- {
- IPHostEntry he = new IPHostEntry();
- ArrayList addrlist = new ArrayList();
-
- he.HostName = h_name;
- he.Aliases = h_aliases;
- for(int i=0; i<h_addrlist.Length; i++) {
- try {
- IPAddress newAddress = IPAddress.Parse(h_addrlist[i]);
-
- if( (Socket.SupportsIPv6 && newAddress.AddressFamily == AddressFamily.InterNetworkV6) ||
- (Socket.SupportsIPv4 && newAddress.AddressFamily == AddressFamily.InterNetwork) )
- addrlist.Add(newAddress);
- } catch (ArgumentNullException) {
- /* Ignore this, as the
- * internal call might have
- * left some blank entries at
- * the end of the array
- */
- }
- }
-
- if(addrlist.Count == 0)
- throw new SocketException(11001);
-
- he.AddressList = addrlist.ToArray(typeof(IPAddress)) as IPAddress[];
- return he;
- }
- }
-}
-
+++ /dev/null
-//
-// System.Net.HttpWebRequest (for 2.1 profile)
-//
-// Authors:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Jb Evain <jbevain@novell.com>
-//
-// Copyright (C) 2007, 2009-2011 Novell, Inc (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System.IO;
-
-namespace System.Net {
-
- // note: the NotImplementedException are needed to match MS implementation
-
- // note: MS documents a lot of thing for this type but, in truth, all happens
- // in a type that derive from HttpWebRequest. In Moonlight case this is either
- // * BrowserHttpWebRequest (browser stack) located in System.Windows.Browser.dll; or
- // * System.Net.Browser.ClientHttpWebRequest (client stack) located in System.Windows.dll
-
- public abstract class HttpWebRequest : WebRequest {
-
- private WebHeaderCollection headers;
-
- protected HttpWebRequest ()
- {
- }
-
- public string Accept {
- get { return Headers [HttpRequestHeader.Accept]; }
- // this header cannot be set directly inside the collection (hence the helper)
- set { Headers.SetHeader ("accept", value); }
- }
-
- public virtual bool AllowReadStreamBuffering {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- // new in SL4 RC
- public virtual bool AllowWriteStreamBuffering {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- public override string ContentType {
- get { return Headers [HttpRequestHeader.ContentType]; }
- // this header cannot be set directly inside the collection (hence the helper)
- set { Headers.SetHeader ("content-type", value); }
- }
-
- public virtual bool HaveResponse {
- get { throw NotImplemented (); }
- }
-
- public override WebHeaderCollection Headers {
- get {
- if (headers == null)
- headers = new WebHeaderCollection (true);
- return headers;
- }
- set {
- // note: this is not a field assignment but a copy (see unit tests)
- // make sure everything we're supplied is valid...
- foreach (string header in value) {
- // anything bad will throw
- WebHeaderCollection.ValidateHeader (header);
- }
- // ... before making those values our own
- Headers.Clear ();
- foreach (string header in value) {
- headers [header] = value [header];
- }
- }
- }
-
- public virtual CookieContainer CookieContainer {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- public override string Method {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- public override Uri RequestUri {
- get { throw NotImplemented (); }
- }
-
- // new in SL4
- public virtual bool SupportsCookieContainer {
- get { return false; }
- }
-
- // new in SL4 (service release) : WP7 binary compatibility - not for use in SL4 applications (MSDN docs)
- public virtual bool AllowAutoRedirect {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- // new in SL4 (service release) : WP7 binary compatibility - not for use in SL4 applications (MSDN docs)
- public string UserAgent {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- public override void Abort ()
- {
- throw NotImplemented ();
- }
-
- public override IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state)
- {
- throw NotImplemented ();
- }
-
- public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
- {
- throw NotImplemented ();
- }
-
- public override Stream EndGetRequestStream (IAsyncResult asyncResult)
- {
- throw NotImplemented ();
- }
-
- public override WebResponse EndGetResponse (IAsyncResult asyncResult)
- {
- throw NotImplemented ();
- }
-
- static Exception NotImplemented ()
- {
- // a bit less IL and hide the "normal" NotImplementedException from corcompare-like tools
- return new NotImplementedException ();
- }
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// System.Net.HttpWebResponse (for 2.1 profile)
-//
-// Authors:
-// Atsushi Enomoto <atsushi@ximian.com>
-// Jb Evain <jbevain@novell.com>
-//
-// Copyright (C) 2007, 2009 Novell, Inc (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net {
-
- public abstract class HttpWebResponse : WebResponse {
-
- public virtual string Method {
- get { throw NotImplemented (); }
- }
-
- public virtual HttpStatusCode StatusCode {
- get { throw NotImplemented (); }
- }
-
- public virtual string StatusDescription {
- get { throw NotImplemented (); }
- }
-
- public virtual CookieCollection Cookies {
- get { throw NotImplemented (); }
- }
-
- static Exception NotImplemented ()
- {
- // hide the "normal" NotImplementedException from corcompare-like tools
- return new NotImplementedException ();
- }
- }
-}
-
-#endif
+++ /dev/null
-// System.Net.IPEndPointCollection
-//
-// Author:
-// Gonzalo Paniagua Javier (gonzalo@novell.com)
-//
-// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-
-using System;
-using System.Collections.ObjectModel;
-
-namespace System.Net {
- public class IPEndPointCollection : Collection<IPEndPoint> {
- public IPEndPointCollection ()
- {
- }
-
- protected override void InsertItem (int index, IPEndPoint item)
- {
- if (item == null)
- throw new ArgumentNullException ("item");
-
- Items.Insert (index, item);
- }
-
- protected override void SetItem (int index, IPEndPoint item)
- {
- if (item == null)
- throw new ArgumentNullException ("item");
-
- Items [index] = item;
- }
- }
-}
-
+++ /dev/null
-/*
- * InternalWebRequestStreamWrapper.cs.
- *
- * Contact:
- * Moonlight List (moonlight-list@lists.ximian.com)
- *
- * Copyright 2008,2010 Novell, Inc. (http://www.novell.com)
- *
- * See the LICENSE file included with the distribution for details.
- *
- */
-
-using System.IO;
-
-namespace System.Net {
-
- internal sealed class InternalWebRequestStreamWrapper : Stream {
-
- MemoryStream stream;
- byte[] data;
-
- internal InternalWebRequestStreamWrapper (MemoryStream s)
- {
- stream = s;
- }
-
- public override bool CanRead {
- get {
- return stream.CanRead;
- }
- }
-
- public override bool CanSeek {
- get {
- return stream.CanSeek;
- }
- }
-
- public override bool CanWrite {
- get {
- return stream.CanWrite;
- }
- }
-
- public override long Length {
- get {
- return stream.Length;
- }
- }
-
- public override long Position {
- get {
- return stream.Position;
- }
- set {
- stream.Position = value;
- }
- }
-
- public override void Flush ()
- {
- stream.Flush ();
- }
-
- public override void Close ()
- {
- try {
- // When we POST data then the actual bytes are needed after the stream is closed (e.g. DRT287)
- // However a MemoryStream will clear itself and throw ObjectDisposedException in such case
- data = stream.ToArray ();
- stream.Close ();
- }
- finally {
- // if used from WebClient then notify that the stream was closed
- if (WebClient != null) {
- WebClient.WriteStreamClosedCallback (WebClientData, data.Length);
- WebClient = null; // notify only once
- }
- }
- }
-
- public override void SetLength (long value)
- {
- stream.SetLength (value);
- }
-
- public override int Read (byte [] buffer, int offset, int count)
- {
- return stream.Read (buffer, offset, count);
- }
-
- public override void Write (byte [] buffer, int offset, int count)
- {
- stream.Write (buffer, offset, count);
- }
-
- public override void WriteByte (byte value)
- {
- stream.WriteByte (value);
- }
-
- public override long Seek (long offset, SeekOrigin origin)
- {
- return stream.Seek (offset, origin);
- }
-
- internal byte[] GetData ()
- {
- // hold a copy of the data if the stream was closed
- return data;
- }
-
- internal MemoryStream InnerStream {
- get { return stream; }
- }
-
- internal WebClient WebClient {
- get; set;
- }
-
- internal object WebClientData {
- get; set;
- }
- }
-}
-
+++ /dev/null
-//
-// System.Net.WebClient
-//
-// Authors:
-// Lawrence Pit (loz@cable.a2000.nl)
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-// Atsushi Enomoto (atsushi@ximian.com)
-// Miguel de Icaza (miguel@ximian.com)
-// Stephane Delcroix (sdelcroix@novell.com)
-//
-// Copyright 2003 Ximian, Inc. (http://www.ximian.com)
-// Copyright 2006, 2008, 2009-2010 Novell, Inc. (http://www.novell.com)
-//
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-
-namespace System.Net {
-
- // note: this type is effectively sealed to transparent code since it's default .ctor is marked with [SecuritySafeCritical]
- public class WebClient {
-
- WebHeaderCollection headers;
- WebHeaderCollection responseHeaders;
- bool response_supports_headers = true; // will be set to false, if needed, when we get a response
- string baseAddress;
- Uri base_address_uri;
- bool is_busy;
- Encoding encoding = Encoding.UTF8;
- bool allow_read_buffering = true;
- bool allow_write_buffering = true;
- WebRequest request;
- object locker;
- CallbackData callback_data;
- long upload_length;
-
- public WebClient ()
- {
- // kind of calling NativeMethods.plugin_instance_get_source_location (PluginHost.Handle)
- // but without adding dependency on System.Windows.dll. GetData is [SecurityCritical]
- // this makes the default .ctor [SecuritySafeCritical] which would be a problem (inheritance)
- // but it happens that MS SL2 also has this default .ctor as SSC :-)
- BaseAddress = (AppDomain.CurrentDomain.GetData ("xap_uri") as string);
- locker = new object ();
- UseDefaultCredentials = true;
- }
-
- // Properties
-
- public string BaseAddress {
- get { return baseAddress; }
- set {
- if (String.IsNullOrEmpty (value)) {
- baseAddress = String.Empty;
- base_address_uri = null;
- } else {
- if (!Uri.TryCreate (value, UriKind.Absolute, out base_address_uri))
- throw new ArgumentException ("Invalid URI");
-
- baseAddress = Uri.UnescapeDataString (base_address_uri.AbsoluteUri);
- }
- }
- }
-
- [MonoTODO ("provide credentials to the client stack")]
- public ICredentials Credentials { get; set; }
-
- // this is an unvalidated collection, HttpWebRequest is responsable to validate it
- public WebHeaderCollection Headers {
- get {
- if (headers == null)
- headers = new WebHeaderCollection ();
-
- return headers;
- }
- set { headers = value; }
- }
-
- public WebHeaderCollection ResponseHeaders {
- get {
- if (!response_supports_headers)
- throw new NotImplementedException ();
- return responseHeaders;
- }
- }
-
- public Encoding Encoding {
- get { return encoding; }
- set {
- if (value == null)
- throw new ArgumentNullException ("value");
- encoding = value;
- }
- }
-
- public bool IsBusy {
- get { return is_busy; }
- }
-
- [MonoTODO ("value is unused, current implementation always works like it's true (default)")]
- public bool AllowReadStreamBuffering {
- get { return allow_read_buffering; }
- set { allow_read_buffering = value; }
- }
-
- // new in SL4 RC
- [MonoTODO ("value is unused, current implementation always works like it's true (default)")]
- public bool AllowWriteStreamBuffering {
- get { return allow_write_buffering; }
- set { allow_write_buffering = value; }
- }
-
- public bool UseDefaultCredentials {
- get; set;
- }
-
- // Methods
-
- void CheckBusy ()
- {
- if (IsBusy)
- throw new NotSupportedException ("WebClient does not support concurrent I/O operations.");
- }
-
- void SetBusy ()
- {
- lock (locker) {
- CheckBusy ();
- is_busy = true;
- }
- }
-
- private string DetermineMethod (Uri address, string method)
- {
- if (method != null)
- return method;
-
- if (address.Scheme == Uri.UriSchemeFtp)
- return "RETR";
- return "POST";
- }
-
- public event DownloadProgressChangedEventHandler DownloadProgressChanged;
- public event DownloadStringCompletedEventHandler DownloadStringCompleted;
- public event OpenReadCompletedEventHandler OpenReadCompleted;
- public event OpenWriteCompletedEventHandler OpenWriteCompleted;
- public event UploadProgressChangedEventHandler UploadProgressChanged;
- public event UploadStringCompletedEventHandler UploadStringCompleted;
- public event WriteStreamClosedEventHandler WriteStreamClosed;
-
- WebRequest SetupRequest (Uri uri, string method, CallbackData callbackData)
- {
- callback_data = callbackData;
- WebRequest request = GetWebRequest (uri);
- // do not send a relative URI to Determine method
- request.Method = DetermineMethod (request.RequestUri, method);
- // copy headers to the request - some needs special treatments
- foreach (string header in Headers) {
- switch (header.ToLowerInvariant ()) {
- case "content-length":
- long cl = 0;
- if (Int64.TryParse (Headers [header], out cl) && (cl >= 0))
- request.ContentLength = cl;
- break;
- case "accept":
- case "content-type":
- // this skip the normal/user validation on headers
- request.Headers.SetHeader (header, Headers [header]);
- break;
- default:
- request.Headers [header] = Headers [header];
- break;
- }
- }
- // original headers are removed after calls
- Headers.Clear ();
- return request;
- }
-
- Stream ProcessResponse (WebResponse response)
- {
- response_supports_headers = response.SupportsHeaders;
- if (response_supports_headers)
- responseHeaders = response.Headers;
-
- HttpWebResponse hwr = (response as HttpWebResponse);
- if (hwr == null)
- throw new NotSupportedException ();
-
- HttpStatusCode status_code = HttpStatusCode.NotFound;
- Stream s = null;
- try {
- status_code = hwr.StatusCode;
- if (status_code == HttpStatusCode.OK)
- s = response.GetResponseStream ();
- }
- catch (Exception e) {
- throw new WebException ("NotFound", status_code == HttpStatusCode.OK ? e : null,
- WebExceptionStatus.UnknownError, response);
- }
- return s;
- }
-
- public void CancelAsync ()
- {
- if (request != null)
- request.Abort ();
- upload_length = 0;
- }
-
- void CompleteAsync ()
- {
- is_busy = false;
- upload_length = 0;
- }
-
- internal class CallbackData {
- public object user_token;
- public SynchronizationContext sync_context;
- public byte [] data;
- public CallbackData (object user_token, byte [] data)
- {
- this.user_token = user_token;
- this.data = data;
- this.sync_context = SynchronizationContext.Current ?? new SynchronizationContext ();
- }
- public CallbackData (object user_token) : this (user_token, null)
- {
- }
- }
-
- // DownloadStringAsync
-
- public void DownloadStringAsync (Uri address)
- {
- DownloadStringAsync (address, null);
- }
-
- public void DownloadStringAsync (Uri address, object userToken)
- {
- if (address == null)
- throw new ArgumentNullException ("address");
-
- lock (locker) {
- SetBusy ();
-
- try {
- request = SetupRequest (address, "GET", new CallbackData (userToken));
- request.BeginGetResponse (new AsyncCallback (DownloadStringAsyncCallback), null);
- }
- catch (Exception e) {
- WebException wex = new WebException ("Could not start operation.", e);
- OnDownloadStringCompleted (
- new DownloadStringCompletedEventArgs (null, wex, false, userToken));
- }
- }
- }
-
- private void DownloadStringAsyncCallback (IAsyncResult result)
- {
- string data = null;
- Exception ex = null;
- bool cancel = false;
- try {
- WebResponse response = request.EndGetResponse (result);
- Stream stream = ProcessResponse (response);
-
- using (StreamReader sr = new StreamReader (stream, encoding, true)) {
- data = sr.ReadToEnd ();
- }
- }
- catch (WebException web) {
- cancel = (web.Status == WebExceptionStatus.RequestCanceled);
- ex = web;
- }
- catch (SecurityException se) {
- // SecurityException inside a SecurityException (not a WebException) for SL compatibility
- ex = new SecurityException (String.Empty, se);
- }
- catch (Exception e) {
- ex = new WebException ("Could not complete operation.", e, WebExceptionStatus.UnknownError, null);
- }
- finally {
- callback_data.sync_context.Post (delegate (object sender) {
- OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (data, ex, cancel, callback_data.user_token));
- }, null);
- }
- }
-
- // OpenReadAsync
-
- public void OpenReadAsync (Uri address)
- {
- OpenReadAsync (address, null);
- }
-
- public void OpenReadAsync (Uri address, object userToken)
- {
- if (address == null)
- throw new ArgumentNullException ("address");
-
- lock (locker) {
- SetBusy ();
-
- try {
- request = SetupRequest (address, "GET", new CallbackData (userToken));
- request.BeginGetResponse (new AsyncCallback (OpenReadAsyncCallback), null);
- }
- catch (Exception e) {
- WebException wex = new WebException ("Could not start operation.", e);
- OnOpenReadCompleted (
- new OpenReadCompletedEventArgs (null, wex, false, userToken));
- }
- }
- }
-
- private void OpenReadAsyncCallback (IAsyncResult result)
- {
- Stream stream = null;
- Exception ex = null;
- bool cancel = false;
- try {
- WebResponse response = request.EndGetResponse (result);
- stream = ProcessResponse (response);
- }
- catch (WebException web) {
- cancel = (web.Status == WebExceptionStatus.RequestCanceled);
- ex = web;
- }
- catch (SecurityException se) {
- // SecurityException inside a SecurityException (not a WebException) for SL compatibility
- ex = new SecurityException (String.Empty, se);
- }
- catch (Exception e) {
- ex = new WebException ("Could not complete operation.", e, WebExceptionStatus.UnknownError, null);
- }
- finally {
- callback_data.sync_context.Post (delegate (object sender) {
- OnOpenReadCompleted (new OpenReadCompletedEventArgs (stream, ex, cancel, callback_data.user_token));
- }, null);
- }
- }
-
- // OpenWriteAsync
-
- public void OpenWriteAsync (Uri address)
- {
- OpenWriteAsync (address, null);
- }
-
- public void OpenWriteAsync (Uri address, string method)
- {
- OpenWriteAsync (address, method, null);
- }
-
- public void OpenWriteAsync (Uri address, string method, object userToken)
- {
- if (address == null)
- throw new ArgumentNullException ("address");
-
- lock (locker) {
- SetBusy ();
-
- try {
- request = SetupRequest (address, method, new CallbackData (userToken));
- request.BeginGetRequestStream (new AsyncCallback (OpenWriteAsyncCallback), null);
- }
- catch (Exception e) {
- WebException wex = new WebException ("Could not start operation.", e);
- OnOpenWriteCompleted (
- new OpenWriteCompletedEventArgs (null, wex, false, userToken));
- }
- }
- }
-
- private void OpenWriteAsyncCallback (IAsyncResult result)
- {
- Stream stream = null;
- Exception ex = null;
- bool cancel = false;
- InternalWebRequestStreamWrapper internal_stream;
-
- try {
- stream = request.EndGetRequestStream (result);
- internal_stream = (InternalWebRequestStreamWrapper) stream;
- internal_stream.WebClient = this;
- internal_stream.WebClientData = callback_data;
- }
- catch (WebException web) {
- cancel = (web.Status == WebExceptionStatus.RequestCanceled);
- ex = web;
- }
- catch (Exception e) {
- ex = new WebException ("Could not complete operation.", e, WebExceptionStatus.UnknownError, null);
- }
- finally {
- callback_data.sync_context.Post (delegate (object sender) {
- OnOpenWriteCompleted (new OpenWriteCompletedEventArgs (stream, ex, cancel, callback_data.user_token));
- }, null);
- }
- }
-
- internal void WriteStreamClosedCallback (object WebClientData, long length)
- {
- try {
- request.BeginGetResponse (OpenWriteAsyncResponseCallback, WebClientData);
- }
- catch (Exception e) {
- callback_data.sync_context.Post (delegate (object sender) {
- OnWriteStreamClosed (new WriteStreamClosedEventArgs (e));
- }, null);
- }
- finally {
- // kind of dummy, 0% progress, that is always emitted
- upload_length = length;
- callback_data.sync_context.Post (delegate (object sender) {
- OnUploadProgressChanged (
- new UploadProgressChangedEventArgs (0, -1, length, -1, 0, callback_data.user_token));
- }, null);
- }
- }
-
- private void OpenWriteAsyncResponseCallback (IAsyncResult result)
- {
- Exception ex = null;
- try {
- WebResponse response = request.EndGetResponse (result);
- ProcessResponse (response);
- }
- catch (SecurityException se) {
- // SecurityException inside a SecurityException (not a WebException) for SL compatibility
- ex = new SecurityException (String.Empty, se);
- }
- catch (Exception e) {
- ex = new WebException ("Could not complete operation.", e, WebExceptionStatus.UnknownError, null);
- }
- finally {
- callback_data.sync_context.Post (delegate (object sender) {
- OnWriteStreamClosed (new WriteStreamClosedEventArgs (ex));
- }, null);
- }
- }
-
- // UploadStringAsync
-
- public void UploadStringAsync (Uri address, string data)
- {
- UploadStringAsync (address, null, data);
- }
-
- public void UploadStringAsync (Uri address, string method, string data)
- {
- UploadStringAsync (address, method, data, null);
- }
-
- public void UploadStringAsync (Uri address, string method, string data, object userToken)
- {
- if (address == null)
- throw new ArgumentNullException ("address");
- if (data == null)
- throw new ArgumentNullException ("data");
-
- lock (locker) {
- SetBusy ();
-
- try {
- CallbackData cbd = new CallbackData (userToken, encoding.GetBytes (data));
- request = SetupRequest (address, method, cbd);
- request.BeginGetRequestStream (new AsyncCallback (UploadStringRequestAsyncCallback), cbd);
- }
- catch (Exception e) {
- WebException wex = new WebException ("Could not start operation.", e);
- OnUploadStringCompleted (
- new UploadStringCompletedEventArgs (null, wex, false, userToken));
- }
- }
- }
-
- private void UploadStringRequestAsyncCallback (IAsyncResult result)
- {
- try {
- Stream stream = request.EndGetRequestStream (result);
- stream.Write (callback_data.data, 0, callback_data.data.Length);
- request.BeginGetResponse (new AsyncCallback (UploadStringResponseAsyncCallback), null);
- }
- catch {
- request.Abort ();
- throw;
- }
- finally {
- // kind of dummy, 0% progress, that is always emitted
- upload_length = callback_data.data.Length;
- callback_data.sync_context.Post (delegate (object sender) {
- OnUploadProgressChanged (
- new UploadProgressChangedEventArgs (0, -1, upload_length, -1, 0, callback_data.user_token));
- }, "null");
- }
- }
-
- private void UploadStringResponseAsyncCallback (IAsyncResult result)
- {
- string data = null;
- Exception ex = null;
- bool cancel = false;
- try {
- WebResponse response = request.EndGetResponse (result);
- Stream stream = ProcessResponse (response);
-
- using (StreamReader sr = new StreamReader (stream, encoding, true)) {
- data = sr.ReadToEnd ();
- }
- }
- catch (WebException web) {
- cancel = (web.Status == WebExceptionStatus.RequestCanceled);
- ex = web;
- }
- catch (SecurityException se) {
- // SecurityException inside a SecurityException (not a WebException) for SL compatibility
- ex = new SecurityException (String.Empty, se);
- }
- catch (Exception e) {
- ex = new WebException ("Could not complete operation.", e, WebExceptionStatus.UnknownError, null);
- }
- finally {
- callback_data.sync_context.Post (delegate (object sender) {
- OnUploadStringCompleted (new UploadStringCompletedEventArgs (data, ex, cancel, callback_data.user_token));
- }, null);
- }
- }
-
- protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
- {
- DownloadProgressChangedEventHandler handler = DownloadProgressChanged;
- if (handler != null)
- handler (this, e);
- }
-
- protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs e)
- {
- CompleteAsync ();
- OpenReadCompletedEventHandler handler = OpenReadCompleted;
- if (handler != null)
- handler (this, e);
- }
-
- protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs e)
- {
- CompleteAsync ();
- DownloadStringCompletedEventHandler handler = DownloadStringCompleted;
- if (handler != null)
- handler (this, e);
- }
-
- protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs e)
- {
- CompleteAsync ();
- OpenWriteCompletedEventHandler handler = OpenWriteCompleted;
- if (handler != null)
- handler (this, e);
- }
-
- protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
- {
- UploadProgressChangedEventHandler handler = UploadProgressChanged;
- if (handler != null)
- handler (this, e);
- }
-
- protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs e)
- {
- CompleteAsync ();
- UploadStringCompletedEventHandler handler = UploadStringCompleted;
- if (handler != null)
- handler (this, e);
- }
-
- protected virtual void OnWriteStreamClosed (WriteStreamClosedEventArgs e)
- {
- CompleteAsync ();
- WriteStreamClosedEventHandler handler = WriteStreamClosed;
- if (handler != null)
- handler (this, e);
- }
-
- protected virtual WebRequest GetWebRequest (Uri address)
- {
- if (address == null)
- throw new ArgumentNullException ("address");
-
- // if the URI is relative then we use our base address URI to make an absolute one
- Uri uri = address.IsAbsoluteUri || base_address_uri == null ? address : new Uri (base_address_uri, address);
-
- HttpWebRequest request = (HttpWebRequest) WebRequest.Create (uri);
- request.AllowReadStreamBuffering = AllowReadStreamBuffering;
- request.AllowWriteStreamBuffering = AllowWriteStreamBuffering;
- request.UseDefaultCredentials = UseDefaultCredentials;
-
- request.progress = delegate (long read, long length) {
- callback_data.sync_context.Post (delegate (object sender) {
- if (upload_length > 0) {
- // always emitted as 50% with an unknown (-1) TotalBytesToSend
- OnUploadProgressChanged (new UploadProgressChangedEventArgs (read, length,
- upload_length, -1, 50, callback_data.user_token));
- } else {
- OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (read, length,
- callback_data.user_token));
- }
- }, null);
- };
- return request;
- }
-
- protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
- {
- return request.EndGetResponse (result);
- }
- }
-}
-
+++ /dev/null
-// System.Net.WebExceptionStatus.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// originally autogenerated by Sergey Chaban (serge@wildwestsoftware.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net {
- public enum WebExceptionStatus {
- Success = 0,
- ConnectFailure = 2,
- SendFailure = 4,
- RequestCanceled = 6,
- Pending = 13,
- UnknownError = 16,
- MessageLengthLimitExceeded = 17,
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// System.Net.WebHeaderCollection (for 2.1 profile)
-//
-// Authors:
-// Jb Evain <jbevain@novell.com>
-// Sebastien Pouliot <sebastien@ximian.com>
-// Lawrence Pit (loz@cable.a2000.nl)
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-// Miguel de Icaza (miguel@novell.com)
-//
-// Copyright 2003 Ximian, Inc. (http://www.ximian.com)
-// (c) 2007, 2009-2010 Novell, Inc. (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace System.Net {
-
- public sealed class WebHeaderCollection : IEnumerable {
-
- Dictionary<string, string> headers;
- bool validate;
-
- public WebHeaderCollection ()
- : this (false)
- {
- }
-
- internal WebHeaderCollection (bool restrict)
- {
- validate = restrict;
- headers = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
- }
-
- public int Count {
- get { return headers.Count; }
- }
-
- public string [] AllKeys {
- get {
- var keys = new string [headers.Count];
- headers.Keys.CopyTo (keys, 0);
- return keys;
- }
- }
-
- public string this [string header] {
- get {
- if (header == null)
- throw new ArgumentNullException ("header");
-
- string value = null;
- headers.TryGetValue (header, out value);
- return value;
- }
- set {
- if (header == null)
- throw new ArgumentNullException ("header");
- if (!IsHeaderName (header))
- throw new ArgumentException ("header");
-
- if (validate)
- ValidateHeader (header);
-
- // null value are ignored (see moon-unit)
- if (value == null)
- return;
- if (!IsHeaderValue (value))
- throw new ArgumentException ("value");
-
- headers [header] = value;
- }
- }
-
- public string this [HttpRequestHeader header] {
- get { return this [HttpRequestHeaderToString (header)]; }
- set {
- string h = HttpRequestHeaderToString (header);
- if (validate)
- ValidateHeader (h);
- headers [h] = value;
- }
- }
-
- // some headers cannot be set using the "this" property but by using
- // the right property of the Web[Request|Response]. However the value
- // does end up in the collection (and can be read safely from there)
- internal void SetHeader (string header, string value)
- {
- if (String.IsNullOrEmpty (value))
- headers.Remove (header);
- else
- headers [header] = value;
- }
-
- internal void Clear ()
- {
- headers.Clear ();
- }
-
- internal bool ContainsKey (string key)
- {
- return headers.ContainsKey (key);
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return headers.Keys.GetEnumerator ();
- }
-
- static string HttpResponseHeaderToString (HttpResponseHeader header)
- {
- switch (header) {
- case HttpResponseHeader.CacheControl: return "Cache-Control";
- case HttpResponseHeader.Connection: return "Connection";
- case HttpResponseHeader.Date: return "Date";
- case HttpResponseHeader.KeepAlive: return "Keep-Alive";
- case HttpResponseHeader.Pragma: return "Pragma";
- case HttpResponseHeader.Trailer: return "Trailer";
- case HttpResponseHeader.TransferEncoding: return "Transfer-Encoding";
- case HttpResponseHeader.Upgrade: return "Upgrade";
- case HttpResponseHeader.Via: return "Via";
- case HttpResponseHeader.Warning: return "Warning";
- case HttpResponseHeader.Allow: return "Allow";
- case HttpResponseHeader.ContentLength: return "Content-Length";
- case HttpResponseHeader.ContentType: return "Content-Type";
- case HttpResponseHeader.ContentEncoding: return "Content-Encoding";
- case HttpResponseHeader.ContentLanguage: return "Content-Language";
- case HttpResponseHeader.ContentLocation: return "Content-Location";
- case HttpResponseHeader.ContentMd5: return "Content-MD5";
- case HttpResponseHeader.ContentRange: return "Content-Range";
- case HttpResponseHeader.Expires: return "Expires";
- case HttpResponseHeader.LastModified: return "Last-Modified";
- case HttpResponseHeader.AcceptRanges: return "Accept-Ranges";
- case HttpResponseHeader.Age: return "Age";
- case HttpResponseHeader.ETag: return "ETag";
- case HttpResponseHeader.Location: return "Location";
- case HttpResponseHeader.ProxyAuthenticate: return "Proxy-Authenticate";
- case HttpResponseHeader.RetryAfter: return "Retry-After";
- case HttpResponseHeader.Server: return "Server";
- case HttpResponseHeader.SetCookie: return "Set-Cookie";
- case HttpResponseHeader.Vary: return "Vary";
- case HttpResponseHeader.WwwAuthenticate: return "WWW-Authenticate";
- default:
- throw new IndexOutOfRangeException ();
- }
- }
-
- static string HttpRequestHeaderToString (HttpRequestHeader header)
- {
- switch (header) {
- case HttpRequestHeader.CacheControl: return "Cache-Control";
- case HttpRequestHeader.Connection: return "Connection";
- case HttpRequestHeader.Date: return "Date";
- case HttpRequestHeader.KeepAlive: return "Keep-Alive";
- case HttpRequestHeader.Pragma: return "Pragma";
- case HttpRequestHeader.Trailer: return "Trailer";
- case HttpRequestHeader.TransferEncoding: return "Transfer-Encoding";
- case HttpRequestHeader.Upgrade: return "Upgrade";
- case HttpRequestHeader.Via: return "Via";
- case HttpRequestHeader.Warning: return "Warning";
- case HttpRequestHeader.Allow: return "Allow";
- case HttpRequestHeader.ContentLength: return "Content-Length";
- case HttpRequestHeader.ContentType: return "Content-Type";
- case HttpRequestHeader.ContentEncoding: return "Content-Encoding";
- case HttpRequestHeader.ContentLanguage: return "Content-Language";
- case HttpRequestHeader.ContentLocation: return "Content-Location";
- case HttpRequestHeader.ContentMd5: return "Content-MD5";
- case HttpRequestHeader.ContentRange: return "Content-Range";
- case HttpRequestHeader.Expires: return "Expires";
- case HttpRequestHeader.LastModified: return "Last-Modified";
- case HttpRequestHeader.Accept: return "Accept";
- case HttpRequestHeader.AcceptCharset: return "Accept-Charset";
- case HttpRequestHeader.AcceptEncoding: return "Accept-Encoding";
- case HttpRequestHeader.AcceptLanguage: return "Accept-Language";
- case HttpRequestHeader.Authorization: return "Authorization";
- case HttpRequestHeader.Cookie: return "Cookie";
- case HttpRequestHeader.Expect: return "Expect";
- case HttpRequestHeader.From: return "From";
- case HttpRequestHeader.Host: return "Host";
- case HttpRequestHeader.IfMatch: return "If-Match";
- case HttpRequestHeader.IfModifiedSince: return "If-Modified-Since";
- case HttpRequestHeader.IfNoneMatch: return "If-None-Match";
- case HttpRequestHeader.IfRange: return "If-Range";
- case HttpRequestHeader.IfUnmodifiedSince: return "If-Unmodified-Since";
- case HttpRequestHeader.MaxForwards: return "Max-Forwards";
- case HttpRequestHeader.ProxyAuthorization: return "Proxy-Authorization";
- case HttpRequestHeader.Referer: return "Referer";
- case HttpRequestHeader.Range: return "Range";
- case HttpRequestHeader.Te: return "TE";
- case HttpRequestHeader.Translate: return "Translate";
- case HttpRequestHeader.UserAgent: return "User-Agent";
- default:
- throw new IndexOutOfRangeException ();
- }
- }
-
- internal static void ValidateHeader (string header)
- {
- switch (header.ToLowerInvariant ()) {
- case "connection":
- case "date":
- case "keep-alive":
- case "trailer":
- case "transfer-encoding":
- case "upgrade":
- case "via":
- case "warning":
- case "allow":
- case "content-length": // accepted by WebClient, copied to WebRequest.ContentLength (not headers)
- case "content-type": // accepted by WebClient, copied to WebRequest.ContentType
- case "content-location":
- case "content-range":
- case "last-modified":
- case "accept": // accepted by WebClient, copied to HttpWebRequest.Accept
- case "accept-charset":
- case "accept-encoding":
- case "accept-language":
- case "cookie":
- case "expect":
- case "host":
- case "if-modified-since":
- case "max-forwards":
- case "referer":
- case "te":
- case "user-agent":
- // extra (not HttpRequestHeader defined) headers that are not accepted by SL2
- // note: the HttpResponseHeader enum is not available in SL2
- case "accept-ranges":
- case "age":
- case "allowed":
- case "connect":
- case "content-transfer-encoding":
- case "delete":
- case "etag":
- case "get":
- case "head":
- case "location":
- case "options":
- case "post":
- case "proxy-authenticate":
- case "proxy-connection":
- case "public":
- case "put":
- case "request-range":
- case "retry-after":
- case "server":
- case "sec-headertest":
- case "sec-":
- case "trace":
- case "uri":
- case "vary":
- case "www-authenticate":
- case "x-flash-version":
- string msg = String.Format ("'{0}' cannot be modified", header);
- throw new ArgumentException (msg, "header");
- default:
- return;
- }
- }
-
- internal static bool IsHeaderValue (string value)
- {
- // TEXT any 8 bit value except CTL's (0-31 and 127)
- // but including \r\n space and \t
- // after a newline at least one space or \t must follow
- // certain header fields allow comments ()
-
- int len = value.Length;
- for (int i = 0; i < len; i++) {
- char c = value [i];
- if (c == 127)
- return false;
- if (c < 0x20 && (c != '\r' && c != '\n' && c != '\t'))
- return false;
- if (c == '\r' && ++i < len) {
- c = value [i];
- if (c != '\n')
- return false;
- }
- if (c == '\n' && ++i < len) {
- c = value [i];
- if (c != ' ' && c != '\t')
- return false;
- }
- }
-
- return true;
- }
-
- internal static bool IsHeaderName (string name)
- {
- if (name == null || name.Length == 0)
- return false;
-
- int len = name.Length;
- for (int i = 0; i < len; i++) {
- char c = name [i];
- if (c > 126 || !allowed_chars [(int) c])
- return false;
- }
-
- return true;
- }
-
- static bool [] allowed_chars = new bool [126] {
- false, false, false, false, false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, true, false, true, true, true, true, false, false, false, true,
- true, false, true, true, false, true, true, true, true, true, true, true, true, true, true, false,
- false, false, false, false, false, false, true, true, true, true, true, true, true, true, true,
- true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
- false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true,
- true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
- false, true, false
- };
- }
-}
-
-#endif
+++ /dev/null
-//
-// System.Net.WebRequest (for 2.1 profile)
-//
-// Authors:
-// Jb Evain <jbevain@novell.com>
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2008-2010 Novell, Inc (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System.Collections.Generic;
-using System.IO;
-
-namespace System.Net {
-
- public abstract class WebRequest {
-
- const string SystemWindows = "System.Windows, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB";
- const string BrowserStack = "System.Net.Browser.BrowserHttpWebRequestCreator, " + SystemWindows;
- const string ClientStack = "System.Net.Browser.ClientHttpWebRequestCreator, " + SystemWindows;
-
- static IWebRequestCreate default_creator;
- static IWebRequestCreate browser_creator;
- static IWebRequestCreate client_creator;
- static Dictionary<string, IWebRequestCreate> registred_prefixes;
-
- internal Action<long,long> progress;
-
- public abstract string ContentType { get; set; }
- public abstract WebHeaderCollection Headers { get; set; }
- public abstract string Method { get; set; }
- public abstract Uri RequestUri { get; }
-
- public virtual long ContentLength {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- // custom registered prefixes return null (unless they override this)
- public virtual IWebRequestCreate CreatorInstance {
- get { return null; }
- }
-
- public virtual ICredentials Credentials {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- public virtual bool UseDefaultCredentials {
- get { throw NotImplemented (); }
- set { throw NotImplemented (); }
- }
-
- static WebRequest ()
- {
- registred_prefixes = new Dictionary<string, IWebRequestCreate> (StringComparer.OrdinalIgnoreCase);
- browser_creator = (IWebRequestCreate) Activator.CreateInstance (Type.GetType (BrowserStack));
- client_creator = (IWebRequestCreate) Activator.CreateInstance (Type.GetType (ClientStack));
- default_creator = browser_creator;
- }
-
- protected WebRequest ()
- {
- }
-
- public abstract void Abort();
- public abstract IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state);
- public abstract IAsyncResult BeginGetResponse (AsyncCallback callback, object state);
- public abstract Stream EndGetRequestStream (IAsyncResult asyncResult);
- public abstract WebResponse EndGetResponse (IAsyncResult asyncResult);
-
- internal virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state, bool policy)
- {
- return BeginGetResponse (callback, state);
- }
-
- public static WebRequest Create (string requestUriString)
- {
- return Create (new Uri (requestUriString));
- }
-
- public static WebRequest Create (Uri requestUri)
- {
- if (requestUri == null)
- throw new ArgumentNullException ("requestUri");
- if (!requestUri.IsAbsoluteUri)
- throw new InvalidOperationException ("This operation is not supported for a relative URI.");
-
- IWebRequestCreate creator = null;
- int n = -1;
- // look for the most promising match in the registred prefixes
- foreach (KeyValuePair<string, IWebRequestCreate> kvp in registred_prefixes) {
- string key = kvp.Key;
- if ((key.Length > n) && requestUri.AbsoluteUri.StartsWith (key)) {
- creator = kvp.Value;
- n = key.Length;
- }
- }
-
- // 'http:/[/]' or 'https:/[/]' needs to be registred otherwise it gets ignored
- // note that this is unlike other protocols (e.g. 'ftp') - see unit tests
- string scheme = requestUri.Scheme;
- if ((scheme == "http" && n <= 5) || (scheme == "https" && n <= 6))
- creator = default_creator;
-
- if (creator == null)
- throw new NotSupportedException (string.Format ("Scheme {0} not supported", scheme));
-
- return creator.Create (requestUri);
- }
-
- public static HttpWebRequest CreateHttp (string requestUriString)
- {
- return CreateHttp (new Uri (requestUriString));
- }
-
- public static HttpWebRequest CreateHttp (Uri requestUri)
- {
- if (requestUri == null)
- throw new ArgumentNullException ("requestUri");
- if (!requestUri.IsAbsoluteUri)
- throw new InvalidOperationException ("Uri is not absolute.");
-
- // we do not check the registred prefixes from CreateHttp and *always* use the client HTTP stack
- switch (requestUri.Scheme) {
- case "http":
- case "https":
- return (HttpWebRequest) client_creator.Create (requestUri);
- default:
- throw new NotSupportedException (string.Format ("Scheme {0} not supported", requestUri.Scheme));
- }
- }
-
- // We can register for
- // * a protocol (e.g. http) for all requests
- // * a protocol (e.g. https) for a domain
- // * a protocol (e.g. http) for a single request
- //
- // See "How to: Specify Browser or Client HTTP Handling" for more details
- // http://msdn.microsoft.com/en-us/library/dd920295%28VS.95%29.aspx
- public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
- {
- if (prefix == null)
- throw new ArgumentNullException ("prefix");
- if (creator == null)
- throw new ArgumentNullException ("creator");
-
- Uri uri;
- if (Uri.TryCreate (prefix, UriKind.Absolute, out uri)) {
- // if a valid URI is supplied then only register the scheme + domain
- prefix = uri.Scheme + Uri.SchemeDelimiter + uri.DnsSafeHost;
- }
-
- // registering 'http', 'http://' or even 'http:/' are all ok - but *never* would 'http:' be correct!
- if ((String.Compare (prefix, "http:", StringComparison.OrdinalIgnoreCase) == 0) ||
- (String.Compare (prefix, "https:", StringComparison.OrdinalIgnoreCase) == 0))
- return false;
-
- if (registred_prefixes.ContainsKey (prefix))
- return false;
-
- registred_prefixes.Add (prefix, creator);
- return true;
- }
-
- static Exception NotImplemented ()
- {
- // hide the "normal" NotImplementedException from corcompare-like tools
- return new NotImplementedException ();
- }
- }
-}
-
-#endif
+++ /dev/null
-//
-// System.Net.HttpWebResponse (for 2.1 profile)
-//
-// Authors:
-// Jb Evain <jbevain@novell.com>
-//
-// (c) 2007 Novell, Inc. (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System.IO;
-
-namespace System.Net {
-
- public abstract class WebResponse : IDisposable {
-
- private WebHeaderCollection headers;
-
- public abstract long ContentLength { get; }
- public abstract string ContentType { get; }
- public abstract Uri ResponseUri { get; }
-
- public virtual WebHeaderCollection Headers {
- get {
- if (!SupportsHeaders)
- throw NotImplemented ();
- return headers;
- }
- }
-
- internal WebHeaderCollection InternalHeaders {
- get { return headers; }
- set { headers = value; }
- }
-
- public virtual bool SupportsHeaders {
- get { return false; }
- }
-
- protected WebResponse ()
- {
- }
-
- public abstract void Close ();
- public abstract Stream GetResponseStream ();
-
- void IDisposable.Dispose ()
- {
- Close ();
- }
-
- static Exception NotImplemented ()
- {
- // hide the "normal" NotImplementedException from corcompare-like tools
- return new NotImplementedException ();
- }
- }
-}
-
-#endif
+++ /dev/null
-//
-// WriteStreamClosedEventArgs.cs
-//
-// Author:
-// Rolf Bjarne Kvinge <RKvinge@novell.com>
-//
-// (C) 2009 Novell, Inc. (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System.ComponentModel;
-using System.IO;
-
-namespace System.Net
-{
- public class WriteStreamClosedEventArgs : EventArgs
- {
- Exception exception;
-
- internal WriteStreamClosedEventArgs (Exception exception)
- {
- this.exception = exception;
- }
-
- public Exception Error {
- get { return exception; }
- }
- }
-}
-
-#endif
+++ /dev/null
-//
-// WriteStreamClosedEventHandler.cs
-//
-// Author:
-// Rolf Bjarne Kvinge <RKvinge@novell.com>
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Net
-{
- public delegate void WriteStreamClosedEventHandler (object sender, WriteStreamClosedEventArgs e);
-}
-
-#endif
<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
../../../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
-../../../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
--- /dev/null
+#include mobile_System.Runtime.Serialization.dll.sources
public bool TryReceive (TimeSpan timeout, out Message msg)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
ThrowIfDisposedOrNotOpen ();
msg = null;
msg = message_encoder.ReadMessage (new MemoryStream (bytes), int.MaxValue);
var id = msg.Headers.MessageId;
if (message_ids.Contains (id))
- return TryReceive (timeout - (DateTime.Now - start), out msg);
+ return TryReceive (timeout - (DateTime.UtcNow - start), out msg);
if (id != null) {
message_ids.Enqueue (id);
if (message_ids.Count >= binding_element.TransportSettings.DuplicateMessageHistoryLength)
if (!handle_announce_online)
return; // Offline announcement is done by another DiscoveryChannelDispatcher
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
Communication.Open (timeout);
// and call AnnouncementOnline().
// Published endpoints are added by DicoveryEndpointPublisherBehavior, which is added to each ServiceEndpoint in the primary (non-announcement) service.
if (dx != null) {
foreach (var edm in dx.PublishedEndpoints) {
- client.InnerChannel.OperationTimeout = timeout - (DateTime.Now - start);
+ client.InnerChannel.OperationTimeout = timeout - (DateTime.UtcNow - start);
client.AnnounceOnline (edm);
}
}
if (handle_announce_online)
return; // Offline announcement is done by another DiscoveryChannelDispatcher
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
// and call AnnouncementOnline().
var dx = host.Extensions.Find<DiscoveryServiceExtension> ();
// Published endpoints are added by DicoveryEndpointPublisherBehavior, which is added to each ServiceEndpoint in the primary (non-announcement) service.
if (dx != null) {
foreach (var edm in dx.PublishedEndpoints) {
- client.InnerChannel.OperationTimeout = timeout - (DateTime.Now - start);
+ client.InnerChannel.OperationTimeout = timeout - (DateTime.UtcNow - start);
client.AnnounceOffline (edm);
}
}
// Then close the client.
- Communication.Close (timeout - (DateTime.Now - start));
+ Communication.Close (timeout - (DateTime.UtcNow - start));
}
protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
protected override void OnOpen (TimeSpan timeout)
{
// FIXME: use timeout
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
inner = CreateDiscoveryInnerChannel<TChannel> (factory);
- ((IChannel) inner).Open (timeout - (DateTime.Now - start));
+ ((IChannel) inner).Open (timeout - (DateTime.UtcNow - start));
}
public Message Request (Message msg)
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
+using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
Assert.IsNull (cf.GetProperty<DiscoveryEndpoint> (), "#1");
var ch = cf.CreateChannel (DiscoveryClientBindingElement.DiscoveryEndpointAddress);
Assert.IsNull (ch.GetProperty<DiscoveryEndpoint> (), "#2");
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
ch.Open (TimeSpan.FromSeconds (5));
- Assert.IsTrue (DateTime.Now - start < TimeSpan.FromSeconds (15), "It is likely that FindCriteria.Duration is ignored");
+ Assert.IsTrue (sw.Elapsed < TimeSpan.FromSeconds (15), "It is likely that FindCriteria.Duration is ignored");
}
[Test]
var cf = be.BuildChannelFactory<IDuplexSessionChannel> (bc);
cf.Open ();
var ch = cf.CreateChannel (DiscoveryClientBindingElement.DiscoveryEndpointAddress);
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
ch.Open (TimeSpan.FromSeconds (5));
- Assert.IsTrue (DateTime.Now - start < TimeSpan.FromSeconds (15), "It is likely that FindCriteria.Duration is ignored");
+ Assert.IsTrue (sw.Elapsed < TimeSpan.FromSeconds (15), "It is likely that FindCriteria.Duration is ignored");
}
[Test]
--- /dev/null
+#include mobile_System.ServiceModel.Web.dll.sources
{
// HTTP channel could be accepted while there is no incoming request yet. The reply channel waits for the actual request.
// HTTP channel listeners do not accept more than one channel at a time.
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
TimeSpan waitTimeout;
if (timeout == TimeSpan.MaxValue)
waitTimeout = TimeSpan.FromMilliseconds(int.MaxValue);
else
- waitTimeout = timeout - (DateTime.Now - start);
+ waitTimeout = timeout - (DateTime.UtcNow - start);
accept_channel_handle.WaitOne (waitTimeout);
accept_channel_handle.Reset ();
- TChannel ch = CreateChannel (timeout - (DateTime.Now - start));
+ TChannel ch = CreateChannel (timeout - (DateTime.UtcNow - start));
ch.Closed += delegate {
accept_channel_handle.Set ();
};
public bool TryDequeueRequest (ChannelDispatcher channel, TimeSpan timeout, out HttpContextInfo context)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
context = null;
HttpChannelListenerEntry ce = null;
if (timeout == TimeSpan.MaxValue)
waitTimeout = TimeSpan.FromMilliseconds (int.MaxValue);
bool ret = ce.WaitHandle.WaitOne (waitTimeout);
- return ret && TryDequeueRequest (channel, waitTimeout - (DateTime.Now - start), out context); // recurse, am lazy :/
+ return ret && TryDequeueRequest (channel, waitTimeout - (DateTime.UtcNow - start), out context); // recurse, am lazy :/
}
context = q.Dequeue ();
return true;
return;
close_started = true;
}
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
// FIXME: consider timeout
- AbortConnections (timeout - (DateTime.Now - start));
+ AbortConnections (timeout - (DateTime.UtcNow - start));
- base.OnClose (timeout - (DateTime.Now - start));
+ base.OnClose (timeout - (DateTime.UtcNow - start));
}
protected string GetHeaderItem (string raw)
{
ThrowIfDisposedOrNotOpen ();
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
// FIXME: give max buffer size
var mb = message.CreateBufferedCopy (0x10000);
pc.Status = RemotePeerStatus.Error; // prepare for cases that it resulted in an error in the middle.
var inner = CreateInnerClient (pc);
pc.Channel = inner;
- inner.Open (timeout - (DateTime.Now - start));
- inner.OperationTimeout = timeout - (DateTime.Now - start);
+ inner.Open (timeout - (DateTime.UtcNow - start));
+ inner.OperationTimeout = timeout - (DateTime.UtcNow - start);
inner.Connect (new ConnectInfo () { Address = local_node_address, NodeId = (uint) node.NodeId });
- pc.Instance.WaitForConnectResponse (timeout - (DateTime.Now - start));
+ pc.Instance.WaitForConnectResponse (timeout - (DateTime.UtcNow - start));
pc.Status = RemotePeerStatus.Connected;
}
- pc.Channel.OperationTimeout = timeout - (DateTime.Now - start);
+ pc.Channel.OperationTimeout = timeout - (DateTime.UtcNow - start);
// see [MC-PRCH] 3.2.4.1
if (message.Headers.MessageId == null)
public override bool TryReceive (TimeSpan timeout, out Message message)
{
ThrowIfDisposedOrNotOpen ();
- DateTime start = DateTime.Now;
if (queue.Count > 0 || receive_handle.WaitOne (timeout)) {
message = queue.Dequeue ();
protected override void OnClose (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
if (client_factory != null)
- client_factory.Close (timeout - (DateTime.Now - start));
+ client_factory.Close (timeout - (DateTime.UtcNow - start));
peers.Clear ();
- resolver.Unregister (node.RegisteredId, timeout - (DateTime.Now - start));
+ resolver.Unregister (node.RegisteredId, timeout - (DateTime.UtcNow - start));
node.SetOffline ();
if (listener_host != null)
- listener_host.Close (timeout - (DateTime.Now - start));
+ listener_host.Close (timeout - (DateTime.UtcNow - start));
node.RegisteredId = null;
}
protected override void OnOpen (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
// FIXME: supply maxAddresses
foreach (var a in resolver.Resolve (node.MeshId, 3, timeout))
int port = 0;
var rnd = new Random ();
for (int i = 0; i < 1000; i++) {
- if (DateTime.Now - start > timeout)
+ if (DateTime.UtcNow - start > timeout)
throw new TimeoutException ();
try {
port = rnd.Next (50000, 51000);
// FIXME: remove debugging code
listener_host.UnknownMessageReceived += delegate (object obj, UnknownMessageReceivedEventArgs earg) { Console.WriteLine ("%%%%% UNKOWN MESSAGE " + earg.Message); };
- listener_host.Open (timeout - (DateTime.Now - start));
+ listener_host.Open (timeout - (DateTime.UtcNow - start));
var nid = (ulong) new Random ().Next (0, int.MaxValue);
var ea = new EndpointAddress (uri);
var pna = new PeerNodeAddress (ea, new ReadOnlyCollection<IPAddress> (Dns.GetHostEntry (name).AddressList));
local_node_address = pna;
- node.RegisteredId = resolver.Register (node.MeshId, pna, timeout - (DateTime.Now - start));
+ node.RegisteredId = resolver.Register (node.MeshId, pna, timeout - (DateTime.UtcNow - start));
node.NodeId = nid;
// Add itself to the local list as well.
protected override TChannel OnAcceptChannel (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
// Close channels that are incorrectly kept open first.
var l = new List<TcpDuplexSessionChannel> ();
l.Add (dch);
}
foreach (var dch in l)
- dch.Close (timeout - (DateTime.Now - start));
+ dch.Close (timeout - (DateTime.UtcNow - start));
- TcpClient client = AcceptTcpClient (timeout - (DateTime.Now - start));
+ TcpClient client = AcceptTcpClient (timeout - (DateTime.UtcNow - start));
if (client == null)
return null; // onclose
// TcpReplyChannel requires refreshed connection after each request processing.
internal TcpClient AcceptTcpClient (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
TcpClient client = accepted_clients.Count == 0 ? null : accepted_clients.Dequeue ();
if (client == null) {
}
accept_handles.Remove (wait);
// recurse with new timeout, or return null if it's either being closed or timed out.
- timeout -= (DateTime.Now - start);
+ timeout -= (DateTime.UtcNow - start);
return State == CommunicationState.Opened && timeout > TimeSpan.Zero ? AcceptTcpClient (timeout) : null;
}
continue;
if (((IPEndPoint) dch.TcpClient.Client.RemoteEndPoint).Equals (client.Client.RemoteEndPoint))
// ... then it should be handled in another BeginTryReceive/EndTryReceive loop in ChannelDispatcher.
- return AcceptTcpClient (timeout - (DateTime.Now - start));
+ return AcceptTcpClient (timeout - (DateTime.UtcNow - start));
}
return client;
if (client.Available > 0)
return true;
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
do {
Thread.Sleep (50);
if (client.Available > 0)
return true;
- } while (DateTime.Now - start < timeout);
+ } while (DateTime.UtcNow - start < timeout);
return false;
}
if (timeout <= TimeSpan.Zero)
throw new ArgumentException (String.Format ("Timeout value must be positive value. It was {0}", timeout));
- DateTime start = DateTime.Now;
-
// FIXME: use timeout
if (client == null)
client = ((TcpChannelListener<IReplyChannel>) Manager).AcceptTcpClient (timeout);
{
Logger.LogMessage (MessageLogSourceKind.TransportSend, ref message, owner.info.BindingElement.MaxReceivedMessageSize);
- DateTime start = DateTime.Now;
owner.frame.WriteUnsizedMessage (message, timeout);
// FIXME: consider timeout here too.
owner.frame.WriteEndRecord ();
public override bool TryReceiveRequest (TimeSpan timeout, out RequestContext context)
{
try {
- DateTime start = DateTime.Now;
context = ReceiveRequest (timeout);
return context != null;
} catch (Exception ex) {
public override Message Request (Message input, TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
// FIXME: use timeouts.
frame.ProcessPreambleInitiator ();
Logger.LogMessage (MessageLogSourceKind.TransportSend, ref input, int.MaxValue); // It is not a receive buffer
- frame.WriteUnsizedMessage (input, timeout - (DateTime.Now - start));
+ frame.WriteUnsizedMessage (input, timeout - (DateTime.UtcNow - start));
// LAMESPEC: it contradicts the protocol described at section 3.1.1.1.1 in [MC-NMF].
// Moving this WriteEndRecord() after ReadUnsizedMessage() causes TCP connection blocking.
frame.WriteEndRecord ();
- var ret = frame.ReadUnsizedMessage (timeout - (DateTime.Now - start));
+ var ret = frame.ReadUnsizedMessage (timeout - (DateTime.UtcNow - start));
Logger.LogMessage (MessageLogSourceKind.TransportReceive, ref ret, info.BindingElement.MaxReceivedMessageSize);
public override bool TryReceiveRequest (TimeSpan timeout, out RequestContext context)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
if (!inner.TryReceiveRequest (timeout, out context))
return false;
var support = Source.SecuritySupport;
var commAuth = support.TokenAuthenticator as CommunicationSecurityTokenAuthenticator;
if (commAuth != null)
- res = commAuth.Communication.ProcessNegotiation (req, timeout - (DateTime.Now - start));
+ res = commAuth.Communication.ProcessNegotiation (req, timeout - (DateTime.UtcNow - start));
else
throw new MessageSecurityException ("This reply channel does not expect incoming WS-Trust requests");
- context.Reply (res, timeout - (DateTime.Now - start));
- context.Close (timeout - (DateTime.Now - start));
+ context.Reply (res, timeout - (DateTime.UtcNow - start));
+ context.Close (timeout - (DateTime.UtcNow - start));
// wait for another incoming message
- return TryReceiveRequest (timeout - (DateTime.Now - start), out context);
+ return TryReceiveRequest (timeout - (DateTime.UtcNow - start), out context);
break;
}
protected override void OnClose (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
// this implicitly premises: TChannel is IChannel
foreach (IChannel ch in channels)
- ch.Close (timeout - (DateTime.Now - start));
- base.OnClose (timeout - (DateTime.Now - start));
+ ch.Close (timeout - (DateTime.UtcNow - start));
+ base.OnClose (timeout - (DateTime.UtcNow - start));
}
protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
{
Console.WriteLine ("NamedPipeChannelListener.OnAcceptChannel");
- DateTime start = DateTime.Now;
if (active_server != null) {
try {
server_release_handle.WaitOne (timeout);
if (message.Headers.RelatesTo == null)
message.Headers.RelatesTo = request.Headers.MessageId;
- DateTime start = DateTime.Now;
owner.frame.WriteUnsizedMessage (message, timeout);
owner.frame.WriteEndRecord ();
owner.server.Close ();
public override bool TryReceiveRequest (TimeSpan timeout, out RequestContext context)
{
try {
- DateTime start = DateTime.Now;
context = ReceiveRequest (timeout);
return context != null;
} catch (TimeoutException) {
protected override void OnOpen (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
-
// FIXME: use timeout
frame = new TcpBinaryFrameManager (TcpBinaryFrameManager.SingletonUnsizedMode, server, true) { Encoder = this.Encoder };
frame.ProcessPreambleRecipient ();
public override Message Request (Message input, TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
CreateClient (timeout);
if (input.Headers.MessageId == null)
input.Headers.MessageId = new UniqueId ();
- frame.WriteUnsizedMessage (input, timeout - (DateTime.Now - start));
+ frame.WriteUnsizedMessage (input, timeout - (DateTime.UtcNow - start));
frame.WriteEndRecord ();
- var ret = frame.ReadUnsizedMessage (timeout - (DateTime.Now - start));
+ var ret = frame.ReadUnsizedMessage (timeout - (DateTime.UtcNow - start));
frame.ReadEndRecord ();
return ret;
}
protected override TChannel OnAcceptChannel (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
if (channel != null)
if (!accept_handle.WaitOne (timeout))
throw new TimeoutException ();
- channel = PopulateChannel (timeout - (DateTime.Now - start));
+ channel = PopulateChannel (timeout - (DateTime.UtcNow - start));
((CommunicationObject) (object) channel).Closed += delegate {
this.channel = null;
accept_handle.Set ();
if (loop_thread == null)
return;
- close_started = DateTime.Now;
+ close_started = DateTime.UtcNow;
close_timeout = timeout;
loop = false;
creator_handle.Set ();
}
else {
try {
- ch.Close (close_timeout - (DateTime.Now - close_started));
+ ch.Close (close_timeout - (DateTime.UtcNow - close_started));
} catch (Exception ex) {
// FIXME: log it.
Logger.Error (String.Format ("Exception on closing channel ({0})", ch.GetType ()), ex);
if (node == null)
return new RefreshResponseInfo () { Result = RefreshResult.RegistrationNotFound };
node.Refresh ();
- return new RefreshResponseInfo () { Result = RefreshResult.Success, RegistrationLifetime = RefreshInterval - (DateTime.Now - node.LastRefreshTime) };
+ return new RefreshResponseInfo () { Result = RefreshResult.Success, RegistrationLifetime = RefreshInterval - (DateTime.UtcNow - node.LastRefreshTime) };
}
public RegisterResponseInfo Register (RegisterInfo registerInfo)
lock (mesh) {
var node = new Node () { ClientId = clientId, Address = addr };
mesh.Add (node);
- node.LastRefreshTime = DateTime.Now;
+ node.LastRefreshTime = DateTime.UtcNow;
return node;
}
}
public void Refresh ()
{
- LastRefreshTime = DateTime.Now;
+ LastRefreshTime = DateTime.UtcNow;
}
public void Update (PeerNodeAddress addr)
{
Address = addr;
- LastRefreshTime = DateTime.Now;
+ LastRefreshTime = DateTime.UtcNow;
}
}
}
+++ /dev/null
-//
-// BasicHttpSecurity_2_1.cs
-//
-// Author:
-// Atsushi Enomoto <atsushi@ximian.com>
-//
-// Copyright (C) 2008 Novell, Inc. http://www.novell.com
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-using System;
-using System.Net.Security;
-using System.ServiceModel.Channels;
-
-namespace System.ServiceModel
-{
- public sealed class BasicHttpSecurity
- {
- internal BasicHttpSecurity (BasicHttpSecurityMode mode)
- {
- this.mode = mode;
- }
-
- BasicHttpSecurityMode mode;
-
- public BasicHttpSecurityMode Mode {
- get { return mode; }
- set { mode = value; }
- }
- }
-}
protected override void OnClose (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
if (channel.State == CommunicationState.Opened)
channel.Close (timeout);
}
// FIXME: implement ConcurrencyMode check:
// if it is .Single && this instance for a callback channel && the operation is invoked inside service operation, then error.
- DateTime startTime = DateTime.Now;
+ DateTime startTime = DateTime.UtcNow;
OutputChannel.Send (msg, timeout);
- return ((IDuplexChannel) channel).Receive (timeout - (DateTime.Now - startTime));
+ return ((IDuplexChannel) channel).Receive (timeout - (DateTime.UtcNow - startTime));
}
internal IAsyncResult BeginRequest (Message msg, TimeSpan timeout, AsyncCallback callback, object state)
protected override void OnClose (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
base.OnClose (timeout);
loop = false;
- if (!loop_handle.WaitOne (timeout - (DateTime.Now - start)))
+ if (!loop_handle.WaitOne (timeout - (DateTime.UtcNow - start)))
throw new TimeoutException ();
- if (!finish_handle.WaitOne (timeout - (DateTime.Now - start)))
+ if (!finish_handle.WaitOne (timeout - (DateTime.UtcNow - start)))
throw new TimeoutException ();
}
internal override Message RequestCorrelated (Message msg, TimeSpan timeout, IOutputChannel channel)
{
- DateTime startTime = DateTime.Now;
+ DateTime startTime = DateTime.UtcNow;
Message ret = null;
ManualResetEvent wait = new ManualResetEvent (false);
Action<Message> handler = delegate (Message reply) {
};
ReplyHandlerQueue.Enqueue (handler);
channel.Send (msg, timeout);
- if (ret == null && !wait.WaitOne (timeout - (DateTime.Now - startTime)))
+ if (ret == null && !wait.WaitOne (timeout - (DateTime.UtcNow - startTime)))
throw new TimeoutException ();
return ret;
}
void OnCloseOrAbort (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
ReleasePerformanceCounters ();
List<ChannelDispatcherBase> l = new List<ChannelDispatcherBase> (ChannelDispatchers);
foreach (ChannelDispatcherBase e in l) {
try {
- TimeSpan ts = timeout - (DateTime.Now - start);
+ TimeSpan ts = timeout - (DateTime.UtcNow - start);
if (ts < TimeSpan.Zero)
e.Abort ();
else
protected override sealed void OnOpen (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
InitializeRuntime ();
for (int i = 0; i < ChannelDispatchers.Count; i++) {
// Skip ServiceMetadataExtension-based one. special case.
var wait = new ManualResetEvent (false);
cd.Opened += delegate { wait.Set (); };
waits.Add (wait);
- cd.Open (timeout - (DateTime.Now - start));
+ cd.Open (timeout - (DateTime.UtcNow - start));
}
WaitHandle.WaitAll (waits.ToArray ());
sleepTime = 5 * 1000;\r
failTime = 2 * 1000;\r
}\r
- DateTime start = DateTime.Now;\r
+ var sw = global::System.Diagnostics.Stopwatch.StartNew ();\r
Client.Sleep (sleepTime);\r
- DateTime end = DateTime.Now;\r
- TimeSpan diff = end.Subtract (start);\r
+ sw.Stop ();\r
TimeSpan max = TimeSpan.FromMilliseconds(failTime);\r
- Assert.IsTrue (diff < max, "Sleep({0} milisec) must end in less than {1} seconds",sleepTime,failTime);\r
- if (sleepTime > (int) diff.TotalMilliseconds)\r
- Thread.Sleep (sleepTime - (int)diff.TotalMilliseconds); // wait for server thread to release itself\r
+ Assert.IsTrue (sw.Elapsed < max, "Sleep({0} milisec) must end in less than {1} seconds",sleepTime,failTime);\r
+ if (sleepTime > (int) sw.ElapsedMilliseconds)\r
+ Thread.Sleep (sleepTime - (int)sw.ElapsedMilliseconds); // wait for server thread to release itself\r
}\r
\r
[Test]\r
protected override TChannel OnAcceptChannel (TimeSpan timeout)
{
// HTTP channel listeners do not accept more than one channel at a time.
- DateTime start = DateTime.Now;
- accept_channel_handle.WaitOne (timeout - (DateTime.Now - start));
+ DateTime start = DateTime.UtcNow;
+ accept_channel_handle.WaitOne (timeout - (DateTime.UtcNow - start));
accept_channel_handle.Reset ();
- TChannel ch = CreateChannel (timeout - (DateTime.Now - start));
+ TChannel ch = CreateChannel (timeout - (DateTime.UtcNow - start));
ch.Closed += delegate {
accept_channel_handle.Set ();
};
protected override void OnClose (TimeSpan timeout)
{
- DateTime start = DateTime.Now;
+ DateTime start = DateTime.UtcNow;
if (reqctx != null)
reqctx.Close (timeout);
// FIXME: consider timeout
- AbortConnections (timeout - (DateTime.Now - start));
+ AbortConnections (timeout - (DateTime.UtcNow - start));
- base.OnClose (timeout - (DateTime.Now - start));
+ base.OnClose (timeout - (DateTime.UtcNow - start));
}
public override bool TryReceiveRequest (TimeSpan timeout, out RequestContext context)
--- /dev/null
+#include mobile_System.ServiceModel.dll.sources
static ServiceInfo DISK_DRIVER_SERVICE = new ServiceInfo { ServiceName = "disk", DisplayName = "Disk Driver", ServiceType = ServiceType.KernelDriver };
static ServiceInfo ROUTING_AND_REMOTE_ACCESS_SERVICE = new ServiceInfo { ServiceName = "RemoteAccess", DisplayName = "Routing and Remote Access", DependedOn = new [] { "bfe", "http", "rasman", "rpcss" } };
static ServiceInfo SECONDARY_LOGON_SERVICE = new ServiceInfo { ServiceName = "seclogon", DisplayName = "Secondary Logon", Dependents = new [] { "te.service" } };
- static ServiceInfo SECURITY_ACCOUNTS_MANAGER_SERVICE = new ServiceInfo { ServiceName = "SamSs", DisplayName = "Security Accounts Manager", Dependents = new [] { "browser", "ktmrm", "lanmanserver", "msdtc" }, DependedOn = new [] { "rpcss" } };
+ static ServiceInfo SECURITY_ACCOUNTS_MANAGER_SERVICE = new ServiceInfo { ServiceName = "SamSs", DisplayName = "Security Accounts Manager", Dependents = new [] { "ktmrm", "lanmanserver", "msdtc" }, DependedOn = new [] { "rpcss" } };
static ServiceInfo COMPLUS_EVENTSYSTEM_SERVICE = new ServiceInfo { ServiceName = "EventSystem", DisplayName = "COM+ Event System", ServiceType = ServiceType.Win32ShareProcess, Dependents = new [] { "comsysapp", "sens" }, DependedOn = new [] { "rpcss" } };
static ServiceInfo WINDOWS_IMAGE_ACQUISITION_SERVICE = new ServiceInfo { ServiceName = "stisvc", DisplayName = "Windows Image Acquisition (WIA)", ServiceType = ServiceType.Win32OwnProcess, DependedOn = new [] { "rpcss" } };
static ServiceInfo WINDOWS_SEARCH_SERVICE = new ServiceInfo { ServiceName = "WSearch", DisplayName = "Windows Search", ServiceType = ServiceType.Win32OwnProcess, Dependents = new [] { "wmpnetworksvc", "workfolderssvc" }, DependedOn = new [] { "rpcss" } };
static ServiceInfo WINDOWS_TIME_SERVICE = new ServiceInfo { ServiceName = "W32Time", DisplayName = "Windows Time" };
static ServiceInfo WINDOWS_UPDATE_SERVICE = new ServiceInfo { ServiceName = "wuauserv", DisplayName = "Windows Update", DependedOn = new [] { "rpcss" } };
- static ServiceInfo WORKSTATION_SERVICE = new ServiceInfo { ServiceName = "LanmanWorkstation", DisplayName = "Workstation", Dependents = new [] { "browser", "netlogon", "sessionenv" }, DependedOn = new [] { "bowser", "mrxsmb20", "nsi" } };
+ static ServiceInfo WORKSTATION_SERVICE = new ServiceInfo { ServiceName = "LanmanWorkstation", DisplayName = "Workstation", Dependents = new [] { "netlogon", "sessionenv" }, DependedOn = new [] { "bowser", "mrxsmb20", "nsi" } };
// A service which is expected to be disabled by default on all supported Windows versions.
static ServiceInfo DISABLED_SERVICE = ROUTING_AND_REMOTE_ACCESS_SERVICE;
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;
}
public class DiscoveryClientProtocolTest {
[Test] // Covers #36116
- [Category ("InetAccess")]
+ [Category ("NotWorking")]
public void ReadWriteTest ()
{
string directory = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ());
--- /dev/null
+#include mobile_System.Web.Services.dll.sources
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)
--- /dev/null
+#include mobile_System.Xml.dll.sources
internal async Task<int> InnerRead (bool sync, int requestedSize, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested ();
- Debug ("InnerRead: {0} {1} {2} {3}", readBuffer.Offset, readBuffer.Size, readBuffer.Remaining, requestedSize);
+ Debug ("InnerRead: {0} {1} {2} {3} {4}", sync, readBuffer.Offset, readBuffer.Size, readBuffer.Remaining, requestedSize);
var len = System.Math.Min (readBuffer.Remaining, requestedSize);
if (len == 0)
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
+using System.Threading;
using System.Threading.Tasks;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
readonly NetworkStream networkStream;
readonly HttpWebRequest request;
+ readonly MonoTlsSettings settings;
+
internal HttpWebRequest Request {
get { return request; }
}
internal IMonoSslStream SslStream {
get { return sslStream; }
}
+#else
+ const string EXCEPTION_MESSAGE = "System.Net.Security.SslStream is not supported on the current platform.";
#endif
WebExceptionStatus status;
get; set;
}
-#if SECURITY_DEP
-// readonly ChainValidationHelper validationHelper;
- readonly MonoTlsSettings settings;
-
public MonoTlsStream (HttpWebRequest request, NetworkStream networkStream)
{
+#if SECURITY_DEP
this.request = request;
this.networkStream = networkStream;
provider = request.TlsProvider ?? MonoTlsProviderFactory.GetProviderInternal ();
status = WebExceptionStatus.SecureChannelFailure;
- /*validationHelper =*/ ChainValidationHelper.Create (provider, ref settings, this);
+ ChainValidationHelper.Create (provider, ref settings, this);
+#else
+ status = WebExceptionStatus.SecureChannelFailure;
+ throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
+#endif
}
internal Stream CreateStream (byte[] buffer)
{
+#if SECURITY_DEP
sslStream = provider.CreateSslStream (networkStream, false, settings);
try {
ServicePointManager.CheckCertificateRevocationList);
status = WebExceptionStatus.Success;
- } catch (Exception) {
+ } catch {
status = WebExceptionStatus.SecureChannelFailure;
throw;
} finally {
}
return sslStream.AuthenticatedStream;
- }
+#else
+ throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
#endif
+ }
}
}
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);
if (proc == IntPtr.Zero)
throw new ArgumentException ("Can't find process with ID " + processId.ToString ());
- return (new Process (new SafeProcessHandle (proc, false), processId));
+ /* The handle returned by GetProcess_internal is owned by its caller, so we must pass true to SafeProcessHandle */
+ return (new Process (new SafeProcessHandle (proc, true), processId));
}
public static Process[] GetProcessesByName(string processName, string machineName)
data = (DefaultWatcherData) watches [fsw];
if (data != null) {
data.Enabled = false;
- data.DisabledTime = DateTime.Now;
+ data.DisabledTime = DateTime.UtcNow;
}
}
}
{
if (!data.Enabled) {
return (data.DisabledTime != DateTime.MaxValue &&
- (DateTime.Now - data.DisabledTime).TotalSeconds > 5);
+ (DateTime.UtcNow - data.DisabledTime).TotalSeconds > 5);
}
DoFiles (data, data.Directory, dispatch);
} else if (sockaddr.sin_family == AF_PACKET) {
sockaddr_ll sockaddrll = (sockaddr_ll) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_ll));
if (((int)sockaddrll.sll_halen) > sockaddrll.sll_addr.Length){
- Console.Error.WriteLine ("Got a bad hardware address length for an AF_PACKET {0} {1}",
- sockaddrll.sll_halen, sockaddrll.sll_addr.Length);
next = addr.ifa_next;
continue;
}
const int default_timeout = 4000; // 4 sec.
ushort identifier;
- // This value is correct as of Linux kernel version 2.6.25.9
- // See /usr/include/linux/capability.h
- const UInt32 linux_cap_version = 0x20071026;
+ // Request 32-bit capabilities by using version 1
+ const UInt32 _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
static readonly byte [] default_buffer = new byte [0];
cap_user_header_t header = new cap_user_header_t ();
cap_user_data_t data = new cap_user_data_t ();
- header.version = linux_cap_version;
+ header.version = _LINUX_CAPABILITY_VERSION_1;
int ret = -1;
s.SendBufferSize = bytes.Length;
s.SendTo (bytes, bytes.Length, SocketFlags.None, target);
- DateTime sentTime = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
// receive
bytes = new byte [100];
}
throw new NotSupportedException (String.Format ("Unexpected socket error during ping request: {0}", error));
}
- long rtt = (long) (DateTime.Now - sentTime).TotalMilliseconds;
+ long rtt = (long) sw.ElapsedMilliseconds;
int headerLength = (bytes [0] & 0xF) << 2;
int bodyLength = rc - headerLength;
private PingReply SendUnprivileged (IPAddress address, int timeout, byte [] buffer, PingOptions options)
{
#if MONO_FEATURE_PROCESS_START
- DateTime sentTime = DateTime.UtcNow;
+ var sw = Stopwatch.StartNew ();
Process ping = new Process ();
string args = BuildPingArgs (address, timeout, options);
string stderr = ping.StandardError.ReadToEnd ();
#pragma warning restore 219
- trip_time = (long) (DateTime.UtcNow - sentTime).TotalMilliseconds;
+ trip_time = (long) sw.ElapsedMilliseconds;
if (!ping.WaitForExit (timeout) || (ping.HasExited && ping.ExitCode == 2))
status = IPStatus.TimedOut;
else if (ping.ExitCode == 0)
}
}
#else
+#pragma warning disable 618
ConfigurationSettings.GetConfig ("system.net/authenticationModules");
+#pragma warning restore 618
#endif
}
}
public DigestSession ()
{
_nc = 1;
- lastUse = DateTime.Now;
+ lastUse = DateTime.UtcNow;
}
public string Algorithm {
if (request == null)
return null;
- lastUse = DateTime.Now;
+ lastUse = DateTime.UtcNow;
NetworkCredential cred = credentials.GetCredential (request.RequestUri, "digest");
if (cred == null)
return null;
return;
DateTime t = DateTime.MaxValue;
- DateTime now = DateTime.Now;
+ DateTime now = DateTime.UtcNow;
ArrayList list = null;
foreach (int key in cache.Keys) {
DigestSession elem = (DigestSession) cache [key];
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
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)
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
internal FtpWebRequest (Uri uri)
{
this.requestUri = uri;
+#pragma warning disable 618
this.proxy = GlobalProxySelection.Select;
+#pragma warning restore 618
}
static Exception GetMustImplement ()
{
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)
+++ /dev/null
-namespace System.Security.Cryptography.X509Certificates {
-
- public class X509Certificate2 : X509Certificate {
- public X509Certificate2 (byte[] rawData)
- {
- }
- }
-
- public class X509Chain {
- public bool Build (X509Certificate2 cert)
- {
- return false;
- }
- }
-}
-
using System;\r
+using System.Diagnostics;\r
using System.ComponentModel;\r
using System.Web.UI.WebControls;\r
\r
\r
static void Main(string[] args) {\r
Console.WriteLine ("This test should normally take less than a second");\r
- DateTime start = DateTime.Now;\r
+ var sw = Stopwatch.StartNew ();\r
DoTest ();\r
- TimeSpan ts = DateTime.Now - start;\r
+ TimeSpan ts = sw.Elapsed;\r
Console.Write ("Time spent: ");\r
Console.WriteLine (ts.ToString());\r
}\r
byte [] buffer = new byte [200];
// start async Read operation
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
IAsyncResult ar = stdout.BeginRead (buffer, 0, buffer.Length,
new AsyncCallback (Read), stdout);
- Assert.IsTrue ((DateTime.Now - start).TotalMilliseconds < 1000, "#01 BeginRead was not async");
+ Assert.IsTrue (sw.ElapsedMilliseconds < 1000, "#01 BeginRead was not async");
p.WaitForExit ();
Assert.AreEqual (0, p.ExitCode, "#02 script failure");
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncRead ()
{
message = "AsyncRead";
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncWrite ()
{
message = "AsyncWrite";
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncAccept ()
{
IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 16279);
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncConnect ()
{
message = "AsyncConnect";
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncReceive ()
{
message = "AsyncReceive";
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncReceiveFrom ()
{
message = "AsyncReceiveFrom";
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncSend ()
{
message = "AsyncSend";
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncSendTo ()
{
message = "AsyncSendTo";
}
[Test]
- [Category ("InetAccess")]
+ [Category ("NotWorking")]
#if FEATURE_NO_BSD_SOCKETS
[ExpectedException (typeof (PlatformNotSupportedException))]
#endif
}
}
+ // Test case for https://bugzilla.novell.com/show_bug.cgi?id=443346
+ // See also https://bugzilla.xamarin.com/show_bug.cgi?id=52157
[Test]
- [Category ("NotOnMac")]
-#if FULL_AOT_DESKTOP
- [Ignore ("https://bugzilla.xamarin.com/show_bug.cgi?id=52157")]
-#endif
public void ConnectedProperty ()
{
- TcpListener listener = new TcpListener (IPAddress.Loopback, NetworkHelpers.FindFreePort ());
+ var port = NetworkHelpers.FindFreePort ();
+ var listener = new TcpListener (IPAddress.Loopback, port);
listener.Start();
- Socket client = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- client.Connect (IPAddress.Loopback, ((IPEndPoint)listener.LocalEndpoint).Port);
- Socket server = listener.AcceptSocket ();
+ var client = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ client.Connect (IPAddress.Loopback, port);
+ var server = listener.AcceptSocket ();
- try {
- server.EndSend(server.BeginSend (new byte[10], 0, 10, SocketFlags.None, null, null));
+ const int blobSize = 2048;
+
+ // Small send/recv buffers so that our send operation will fill them
+ server.ReceiveBufferSize = server.SendBufferSize = 256;
+ client.ReceiveBufferSize = client.SendBufferSize = 256;
+
+ // Setting this linger state causes shutdown to be a hard close (RST if send data is pending)
+ server.LingerState = client.LingerState = new LingerOption (true, 0);
+
+ // KeepAlive being set introduces another opportunity for a RST according to some documentation
+ server.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
+ client.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
+
+ try
+ {
+ // Fill the send buffer
+ client.Send (new byte[blobSize]);
+ // Now shut down the socket. Because of the linger state this will hard close and send RST.
+ client.Shutdown (SocketShutdown.Both);
client.Close ();
- try {
- server.EndReceive (server.BeginReceive (new byte[10], 0, 10, SocketFlags.None, null, null));
- } catch {
+
+ Assert.IsFalse (client.Connected);
+ Assert.IsTrue (server.Connected);
+
+ var isDead = false;
+
+ try
+ {
+ // On Windows this BeginSend succeeds... it really shouldn't and a sync send fails.
+ // On Linux this fails with a ConnectionReset.
+ var ar = server.BeginSend (new byte[blobSize], 0, blobSize, SocketFlags.None, null, null);
+ // On Mac we get an erroneous WSAESHUTDOWN (10058) here
+ server.EndSend (ar);
+ }
+ catch (SocketException se)
+ {
+ isDead = true;
+
+ if (
+ (se.SocketErrorCode != SocketError.ConnectionReset) &&
+ (se.SocketErrorCode != SocketError.Shutdown)
+ )
+ throw;
+ }
+
+ if (!isDead)
+ {
+ try
+ {
+ // On Windows this second send operation will fail with a ConnectionReset.
+ var ar = server.BeginSend (new byte[blobSize], 0, blobSize, SocketFlags.None, null, null);
+ server.EndSend (ar);
+ }
+ catch (SocketException se)
+ {
+ if (se.SocketErrorCode != SocketError.ConnectionReset)
+ throw;
+ }
}
- Assert.IsTrue (!client.Connected);
- Assert.IsTrue (!server.Connected);
- } finally {
+
+ Assert.IsFalse (client.Connected);
+ Assert.IsFalse (server.Connected);
+ }
+ finally
+ {
listener.Stop ();
client.Close ();
server.Close ();
}
// async tests (for stack propagation)
-/* Oops - not yet implemented in Mono
private void ConnectCallback (IAsyncResult ar)
{
TcpClient c = (TcpClient)ar.AsyncState;
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncConnect_StringIntAsyncCallbackObject ()
{
TcpClient s = new TcpClient ();
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncConnect_IPAddressIntAsyncCallbackObject ()
{
IPHostEntry host = Dns.Resolve ("www.google.com");
[Test]
[EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
- [Category ("InetAccess")]
public void AsyncConnect_IPAddressArrayIntAsyncCallbackObject ()
{
IPHostEntry host = Dns.Resolve ("www.google.com");
Assert.Ignore ("Timeout");
Assert.IsNull (message, message);
}
-*/
}
}
}
[Test]
- [Category("InetAccess")]
#if FEATURE_NO_BSD_SOCKETS
[ExpectedException (typeof (PlatformNotSupportedException))]
#endif
}
[Test]
- //[Category("InetAccess")]
[Category ("NotWorking")] // Disabled until a server that meets requirements is found
public void Cookies1 ()
{
req.Headers.Add (HttpRequestHeader.IfNoneMatch, "898bbr2347056cc2e096afc66e104653");
req.IfModifiedSince = new DateTime (2010, 01, 04);
- DateTime start = DateTime.Now;
+ var sw = global::System.Diagnostics.Stopwatch.StartNew ();
HttpWebResponse response = null;
try {
Assert.AreEqual (0, bytesRead, "#3");
}
- TimeSpan elapsed = DateTime.Now - start;
+ TimeSpan elapsed = sw.Elapsed;
Assert.IsTrue (elapsed.TotalMilliseconds < 2000, "#4");
}
}
var req = (HttpWebRequest) WebRequest.Create (url_to_test);
req.Timeout = TimeOutInMilliSeconds;
- Start = DateTime.Now;
+ Start = DateTime.UtcNow;
using (var resp = (HttpWebResponse) req.GetResponse ())
{
var sr = new StreamReader (resp.GetResponseStream (), Encoding.UTF8);
Body = sr.ReadToEnd ();
}
} catch (Exception e) {
- End = DateTime.Now;
+ End = DateTime.UtcNow;
Exception = e;
}
}
}\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
-//\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);
+ }
+*/
+}
+}
+
}
[Test]
- [Category ("InetAccess")]
public void DownloadTwice ()
{
WebClient wc = new WebClient();
}
[Test]
- [Category("InetAccess")]
public void DownloadFileTaskAsync ()
{
WebClient wc = new WebClient ();
}
[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 ();
}
[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 ();
}
[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 ();
}
[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 ();
}
[Test]
- [Category ("InetAccess")]
public void Build_Cert1_X509RevocationMode_Online ()
{
X509Chain c = new X509Chain ();
--- /dev/null
+#include mobile_System.dll.sources
+++ /dev/null
-//
-// StrongNameManager.cs - StrongName Management
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2004,2009 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Reflection;
-
-namespace Mono.Security {
-
- internal class StrongNameManager {
-
- static public byte[] GetMappedPublicKey (byte[] token)
- {
- return token;
- }
-
- static public bool MustVerify (AssemblyName an)
- {
- return true;
- }
- }
-}
-
[ComVisible (true)]
[Serializable]
[Flags]
+ #region Sync with sre-internals.h
public enum AssemblyBuilderAccess {
Run = 1,
Save = 2,
ReflectionOnly = 6,
RunAndCollect = 9
}
+ #endregion
}
_initialLeaseTime = LifetimeServices.LeaseTime;
_renewOnCallTime = LifetimeServices.RenewOnCallTime;
_sponsorshipTimeout = LifetimeServices.SponsorshipTimeout;
- _leaseExpireTime = DateTime.Now + _initialLeaseTime;
+ _leaseExpireTime = DateTime.UtcNow + _initialLeaseTime;
}
public TimeSpan CurrentLeaseTime
{
- get { return _leaseExpireTime - DateTime.Now; }
+ get { return _leaseExpireTime - DateTime.UtcNow; }
}
public LeaseState CurrentState
throw new RemotingException ("InitialLeaseTime property can only be set when the lease is in initial state; state is " + _currentState + ".");
_initialLeaseTime = value;
- _leaseExpireTime = DateTime.Now + _initialLeaseTime;
+ _leaseExpireTime = DateTime.UtcNow + _initialLeaseTime;
if (value == TimeSpan.Zero) _currentState = LeaseState.Null;
}
}
public TimeSpan Renew (TimeSpan renewalTime)
{
- DateTime newTime = DateTime.Now + renewalTime;
+ DateTime newTime = DateTime.UtcNow + renewalTime;
if (newTime > _leaseExpireTime) _leaseExpireTime = newTime;
return CurrentLeaseTime;
}
+++ /dev/null
-//
-// System.Security.Policy.Evidence
-//
-// Authors:
-// Sean MacIsaac (macisaac@ximian.com)
-// Nick Drochak (ndrochak@gol.com)
-// Jackson Harper (Jackson@LatitudeGeo.com)
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2001 Ximian, Inc.
-// Portions (C) 2003, 2004 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-namespace System.Security.Policy {
-
- public sealed class Evidence {
- }
-}
-
-#endif
-
+++ /dev/null
-//
-// System.Security.CodeAccessPermission.cs
-//
-// Authors:
-// Miguel de Icaza (miguel@ximian.com)
-// Nick Drochak, ndrochak@gol.com
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2001 Nick Drochak, All Rights Reserved
-// Portions (C) 2004 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-namespace System.Security {
-
- public abstract class CodeAccessPermission {
- }
-}
-
+++ /dev/null
-//
-// System.Security.PermissionSet.cs
-//
-// Authors:
-// Nick Drochak(ndrochak@gol.com)
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) Nick Drochak
-// Portions (C) 2003, 2004 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections;
-using System.Diagnostics;
-using System.IO;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
-using System.Runtime.Serialization.Formatters.Binary;
-using System.Security.Permissions;
-using System.Security.Policy;
-using System.Text;
-using System.Threading;
-
-namespace System.Security {
-
- [Serializable]
- public class PermissionSet {
-
- public PermissionSet ()
- {
- }
-
- public PermissionSet (PermissionState state)
- {
- }
-
- public PermissionSet (PermissionSet permSet)
- {
- }
-
- public IPermission AddPermission (IPermission perm)
- {
- return perm;
- }
-
- public bool IsUnrestricted ()
- {
- return true;
- }
-
- public PermissionSet Union (PermissionSet other)
- {
- return new PermissionSet ();
- }
- }
-}
+++ /dev/null
-//
-// System.Security.SecurityException.cs
-//
-// Authors:
-// Nick Drochak(ndrochak@gol.com)
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) Nick Drochak
-// (C) 2004 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005,2009 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Globalization;
-using System.Runtime.InteropServices;
-
-namespace System.Security {
-
- [ComVisible (true)]
- public class SecurityException : SystemException {
-
-
- public SecurityException ()
- : base (Locale.GetText ("A security error has been detected."))
- {
- base.HResult = unchecked ((int)0x8013150A);
- }
-
- public SecurityException (string message)
- : base (message)
- {
- base.HResult = unchecked ((int)0x8013150A);
- }
-
- public SecurityException (string message, Exception inner)
- : base (message, inner)
- {
- base.HResult = unchecked ((int)0x8013150A);
- }
-
- public override string ToString ()
- {
- return base.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// System.AppDomainManager class
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2004-2005,2009 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-#if MOBILE
-
-using System.Runtime.InteropServices;
-using System.Security;
-
-namespace System {
-
-#if MONO_FEATURE_MULTIPLE_APPDOMAINS
- [ComVisible (true)]
- public class AppDomainManager {
-
- public AppDomainManager ()
- {
- }
-
- [MonoTODO]
- public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo)
- {
- }
-
- [MonoTODO]
- public virtual bool CheckSecuritySettings (SecurityState state)
- {
- return (state != null);
- }
- }
-#else
- [Obsolete ("AppDomainManager is not supported on the current platform.", true)]
- public class AppDomainManager {
-
- public AppDomainManager ()
- {
- get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
- }
-
- public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo)
- {
- get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
- }
-
- public virtual bool CheckSecuritySettings (SecurityState state)
- {
- get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
- }
- }
-#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
-}
-
-#endif
-
string subKeyName = Guid.NewGuid ().ToString ();
try {
- object rawValue = DateTime.Now;
+ object rawValue = DateTime.UtcNow;
using (RegistryKey createdKey = Registry.CurrentUser.CreateSubKey (subKeyName)) {
// we created a new subkey, so value should not exist
public void LastAccessTimeUtc ()
{
DirectoryInfo info = new DirectoryInfo (TempFolder);
- info.LastAccessTimeUtc = DateTime.Now;
+ info.LastAccessTimeUtc = DateTime.UtcNow;
}
[Test]
public void CreationTimeUtc ()
{
DirectoryInfo info = new DirectoryInfo (TempFolder);
- info.CreationTimeUtc = DateTime.Now;
+ info.CreationTimeUtc = DateTime.UtcNow;
}
[Test]
--- /dev/null
+//
+// DriveInfoTest.cs - NUnit Test Cases for System.IO.DriveInfo class
+//
+// Authors
+// Alexander Köplinger <alkpli@microsoft.com>
+//
+// Copyright (c) 2017 Xamarin, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+
+using NUnit.Framework;
+
+namespace MonoTests.System.IO
+{
+ [TestFixture]
+ public class DriveInfoTest
+ {
+ [Test]
+ public void Constructor ()
+ {
+ if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+ Assert.Ignore ("The Jenkins builders don't have '/' mounted, just testing Windows for now.");
+
+ var drive = new DriveInfo ("C:\\");
+ ValidateDriveInfo (drive);
+ Assert.AreEqual (DriveType.Fixed, drive.DriveType);
+ }
+
+ [Test]
+ public void ConstructorThrowsOnNonExistingDrive ()
+ {
+ Assert.Throws<ArgumentException> (() => new DriveInfo ("/monodriveinfotest"));
+ }
+
+ [Test]
+ public void GetDrivesNotEmpty ()
+ {
+ var drives = DriveInfo.GetDrives ();
+ CollectionAssert.IsNotEmpty (drives);
+ }
+
+ [Test]
+ public void GetDrivesValidInfo ()
+ {
+ var drives = DriveInfo.GetDrives ();
+
+ foreach (var d in drives) {
+ ValidateDriveInfo (d);
+ }
+ }
+
+ void ValidateDriveInfo (DriveInfo d)
+ {
+ AssertHelper.IsNotEmpty (d.Name);
+ AssertHelper.IsNotEmpty (d.VolumeLabel);
+ Assert.NotNull (d.RootDirectory);
+
+ if (d.DriveFormat != null) {
+ Assert.AreNotEqual ("", d.DriveFormat);
+ Assert.AreNotEqual (DriveType.Unknown, d.DriveType, "DriveFormat=" + d.DriveFormat);
+ }
+
+ if (d.DriveType == DriveType.Fixed) { // just consider fixed drives for now
+ Assert.True (d.IsReady);
+ AssertHelper.GreaterOrEqual (d.AvailableFreeSpace, 0);
+ AssertHelper.GreaterOrEqual (d.TotalFreeSpace, 0);
+ AssertHelper.GreaterOrEqual (d.TotalSize, 0);
+ }
+ }
+ }
+}
}
}
+ [Test]
+ public void Delete_NonExisting_NoException ()
+ {
+ File.Delete (Path.Combine (Directory.GetDirectoryRoot (Directory.GetCurrentDirectory ()), "monononexistingfile.dat"));
+ }
+
[Test]
public void GetAttributes_Archive ()
{
} catch (NotSupportedException e) {
}
}
+
+ class AssemblyBuilderResolver {
+ private Assembly mock;
+ private ResolveEventHandler d;
+ private string theName;
+
+ public AssemblyBuilderResolver (string theName) {
+ mock = CreateMock (theName);
+ d = new ResolveEventHandler (HandleResolveEvent);
+ this.theName = theName;
+ }
+
+ public void StartHandling () {
+ AppDomain.CurrentDomain.AssemblyResolve += d;
+ }
+
+ public void StopHandling () {
+ AppDomain.CurrentDomain.AssemblyResolve -= d;
+ }
+
+ public Assembly HandleResolveEvent (Object sender, ResolveEventArgs args) {
+ if (args.Name.StartsWith (theName))
+ return mock;
+ else
+ return null;
+ }
+
+ private static Assembly CreateMock (string name) {
+ var an = new AssemblyName (name);
+ var ab = AssemblyBuilder.DefineDynamicAssembly (an, AssemblyBuilderAccess.ReflectionOnly);
+ var mb = ab.DefineDynamicModule (an.Name);
+
+ // Just make some content for the assembly
+ var tb = mb.DefineType ("Foo", TypeAttributes.Public);
+ tb.DefineDefaultConstructor (MethodAttributes.Public);
+
+ tb.CreateType ();
+
+ return ab;
+ }
+ }
+
+ [Test]
+ public void ResolveEventHandlerReflectionOnlyError ()
+ {
+ // Regression test for 57850.
+
+ // If a ResolveEventHandler returns a reflection-only
+ // AssemblyBuilder, we should throw a FileNotFoundException.
+ var s = "ResolveEventHandlerReflectionOnlyErrorAssembly";
+ var h = new AssemblyBuilderResolver (s);
+ Assert.Throws<FileNotFoundException>(() => {
+ h.StartHandling ();
+ var aName = new AssemblyName (s);
+ try {
+ AppDomain.CurrentDomain.Load (aName);
+ } finally {
+ h.StopHandling ();
+ }
+ });
+ }
+
+
}
}
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);
}
[Test]
[ExpectedException (typeof (NotSupportedException))]
- [Category ("ValueAdd")]
public void TestFindMembersIncomplete ()
{
EnumBuilder enumBuilder = GenerateEnum ();
[Test]
[ExpectedException (typeof (NotSupportedException))]
- [Category ("ValueAdd")]
public void TestGetConstructorIncomplete ()
{
EnumBuilder enumBuilder = GenerateEnum ();
//
using System;
+using System.Diagnostics;
using System.Threading;
using NUnit.Framework;
else
ThreadPool.QueueUserWorkItem (_ => { Interlocked.Increment (ref sum); Interlocked.Increment (ref total); });
}
- var start = DateTime.Now;
- while ((total != n || sum != 0) && (DateTime.Now - start).TotalSeconds < 60)
+ var sw = Stopwatch.StartNew ();
+ while ((total != n || sum != 0) && sw.Elapsed.TotalSeconds < 60)
Thread.Sleep (1000);
Assert.IsTrue (total == n, "#1");
Assert.IsTrue (sum == 0, "#2");
public void GetAvailableThreads ()
{
ManualResetEvent mre = new ManualResetEvent (false);
- DateTime start = DateTime.Now;
+ var sw = Stopwatch.StartNew ();
int i, workerThreads, completionPortThreads;
try {
Console.WriteLine ("workerThreads = {0}, completionPortThreads = {1}", workerThreads, completionPortThreads);
- if ((DateTime.Now - start).TotalSeconds >= 10)
+ if (sw.Elapsed.TotalSeconds >= 10)
Assert.Fail ("did not reach 0 available threads");
ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
public static void WhileAlive (Thread t, bool alive, string s)
{
- DateTime ti = DateTime.Now;
+ var sw = SD.Stopwatch.StartNew ();
while (t.IsAlive == alive) {
- if ((DateTime.Now - ti).TotalSeconds > 10) {
+ if (sw.Elapsed.TotalSeconds > 10) {
if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
else Assert.Fail ("Timeout while waiting for alive state. " + s);
}
public static bool WhileAliveOrStop (Thread t, bool alive, string s)
{
- DateTime ti = DateTime.Now;
+ var sw = SD.Stopwatch.StartNew ();
while (t.IsAlive == alive) {
if (t.ThreadState == ThreadState.Stopped)
return false;
- if ((DateTime.Now - ti).TotalSeconds > 10) {
+ if (sw.Elapsed.TotalSeconds > 10) {
if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
else Assert.Fail ("Timeout while waiting for alive state. " + s);
}
using System;
+using System.Diagnostics;
using System.Collections.Generic;
using System.Threading;
Thread.Sleep (10); // wait a bit so we enter mre.WaitOne
- DateTime end = DateTime.Now.AddMilliseconds (500);
- while (DateTime.Now < end) {
+ var sw = Stopwatch.StartNew ();
+ while (sw.ElapsedMilliseconds <= 500) {
thread.Suspend ();
thread.Resume ();
}
Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAny ({mre1, mre2})
- DateTime end = DateTime.Now.AddMilliseconds (500);
- while (DateTime.Now < end) {
+ var sw = Stopwatch.StartNew ();
+ while (sw.ElapsedMilliseconds <= 500) {
thread.Suspend ();
thread.Resume ();
}
Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAll ({mre1, mre2})
- DateTime end = DateTime.Now.AddMilliseconds (500);
- while (DateTime.Now < end) {
+ var sw = Stopwatch.StartNew ();
+ while (sw.ElapsedMilliseconds <= 500) {
thread.Suspend ();
thread.Resume ();
}
[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]
System.IO/BinaryWriterTest.cs
System.IO/BufferedStreamTest.cs
System.IO/DirectoryInfoTest.cs
+System.IO/DriveInfoTest.cs
System.IO/DirectoryTest.cs
System.IO/FileInfoTest.cs
System.IO/FileNotFoundExceptionTest.cs
System.Threading/ThreadLocalTests.cs
System.Threading/SpinLockTests.cs
../../../../mono/mini/TestHelpers.cs
+../../test-helpers/NunitHelpers.cs
{
Assert.That(collection, new EmptyCollectionConstraint(), message, args);
}
+
+ public static void IsNotEmpty(IEnumerable collection, string message = null, params object[] args)
+ {
+ Assert.That(collection, Is.Not.Empty, message, args);
+ }
}
static class FileAssert
Assert.That(arg1, Is.GreaterThan(arg2), message, args);
}
+ public static void Greater(System.DateTime arg1, System.DateTime arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.GreaterThan(arg2), message, args);
+ }
+
public static void GreaterOrEqual(int arg1, int arg2, string message = null, params object[] args)
{
Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args);
Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args);
}
+ public static void GreaterOrEqual(System.DateTime arg1, System.DateTime arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args);
+ }
+
+ public static void GreaterOrEqual(System.TimeSpan arg1, System.TimeSpan arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args);
+ }
+
public static void LessOrEqual (int arg1, int arg2, string message = null, params object[] args)
{
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);
--- /dev/null
+// CS0029: Cannot implicitly convert type `int' to `(long, bool)'
+// Line: 8
+
+class C
+{
+ static void Test ()
+ {
+ System.ValueTuple<long, bool> arg = 1;
+ }
+}
--- /dev/null
+// CS0128: A local variable named `xx' is already defined in this scope
+// Line: 9
+
+class X
+{
+ public static void Main ()
+ {
+ short xx;
+ var (xx, yy) = (1, 'g');
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0815: An implicitly typed local variable declaration cannot be initialized with `(int, method group)'
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = (1, Main);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0826: The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = new [] { (1, Main) };
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0827: An anonymous type property `Prop' cannot be initialized with `(int, method group)'
+// Line: 9
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = new {
+ Prop = (1, Main)
+ };
+ }
+}
\ No newline at end of file
+++ /dev/null
-// CS1026: Unexpected symbol `;', expecting `)'
-// Line: 10
-
-using System;
-
-class Test {
- static void Main ()
- {
- string uri = "http://localhost/";
- int default_port = (uri.StartsWith ("http://") ? 80 : -1;
- }
-}
-// CS1525: Unexpected symbol `==', expecting `type'
+// CS1525: Unexpected symbol `==', expecting `(' or `type'
// Line: 8
class A
-// CS1525: Unexpected symbol `1', expecting `type'
+// CS1525: Unexpected symbol `1', expecting `(' or `type'
// Line: 4
class M : 1
-// CS1525: Unexpected symbol `)', expecting `[', `out', `params', `ref', `this', or `type'
+// CS1525: Unexpected symbol `)', expecting `(', `[', `out', `params', `ref', `this', or `type'
// Line: 6
class TestClass
--- /dev/null
+// CS1026: Unexpected symbol `;', expecting `)' or `,'
+// Line: 10
+
+using System;
+
+class Test {
+ static void Main ()
+ {
+ string uri = "http://localhost/";
+ int default_port = (uri.StartsWith ("http://") ? 80 : -1;
+ }
+}
-// CS1525: Unexpected symbol `this', expecting `[', `{', or `type'
+// CS1525: Unexpected symbol `this', expecting `(', `[', `{', or `type'
// Line: 8
class M
--- /dev/null
+// CS1644: Feature `tuples' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 7
+// Compiler options: -langversion:6
+
+class Class
+{
+ static (int, bool) Foo ()
+ {
+ return;
+ }
+}
--- /dev/null
+// CS1644: Feature `tuples' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 9
+// Compiler options: -langversion:6
+
+class Class
+{
+ static void Main ()
+ {
+ var t = (a: 1, b: 2);
+ }
+}
--- /dev/null
+// CS8123: The tuple element name `a' is ignored because a different name or no name is specified by the target type `(int, int)'
+// Line: 9
+// Compiler options: -warnaserror
+
+class C
+{
+ public static void Main ()
+ {
+ (int tt1, int tt2) t = (a: 1, 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8123: The tuple element name `b' is ignored because a different name or no name is specified by the target type `(long, string)'
+// Line: 9
+// Compiler options: -warnaserror
+
+static class X
+{
+ static (long a, string x) Test ()
+ {
+ return (b: 1, "");
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8124: Tuple must contain at least two elements
+// Line: 6
+
+class X
+{
+ static (int) Foo ()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8125: The tuple element name `Item22' can only be used at position 22
+// Line: 6
+
+class C
+{
+ static void Test ((int Item22, int b) arg)
+ {
+ }
+}
--- /dev/null
+// CS8126: The tuple element name `Rest' is reserved
+// Line: 6
+
+class C
+{
+ static void Test ((int Rest, int b) arg)
+ {
+ }
+}
--- /dev/null
+// CS8127: The tuple element name `a' is a duplicate
+// Line: 6
+
+class C
+{
+ static (int a, int a) Test ()
+ {
+ return null;
+ }
+}
--- /dev/null
+// CS8129:
+// Line:
+
+using System;
+
+class C
+{
+ static void Main ()
+ {
+ long x;
+ string y;
+ (x, y) = new C ();
+ }
+
+ public static void Deconstruct (out int a, out string b)
+ {
+ a = 1;
+ b = "hello";
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8130: Cannot infer the type of implicitly-typed deconstruction variable `yy'
+// Line: 8
+
+class X
+{
+ public static void Main ()
+ {
+ var (xx, yy) = (1, Main);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side
+// Line: 9
+
+class C
+{
+ public static void Main ()
+ {
+ int x, y;
+ (x, y) = null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8132: Cannot deconstruct a tuple of `2' elements into `3' variables
+// Line: 11
+
+class X
+{
+ static int xx;
+ static long yy, zz;
+
+ public static void Main ()
+ {
+ (xx, yy, zz) = Foo ();
+ }
+
+ static (int, long) Foo ()
+ {
+ return (1, 3);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8132: Cannot deconstruct a tuple of `2' elements into `3' variables
+// Line: 8
+
+class C
+{
+ public static void Main ()
+ {
+ var (t, u, v) = (1, 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8133: Cannot deconstruct dynamic objects
+// Line: 9
+
+class C
+{
+ public static void Test (dynamic d)
+ {
+ int x, y;
+ (x, y) = d;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8135: Tuple literal `(int, method group)' cannot be converted to type `object'
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ object m = (1, Main);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8138: Do not use `System.Runtime.CompilerServices.TupleElementNamesAttribute' directly. Use the tuple syntax instead
+// Line: 7
+
+using System;
+using System.Runtime.CompilerServices;
+
+[TupleElementNames (new[] { "a", "b" })]
+public class C
+{
+}
--- /dev/null
+// CS8139: `D.M()': cannot change return type tuple element names when overriding inherited member `C.M()'
+// Line: 14
+
+class C
+{
+ public virtual (int a, int b) M ()
+ {
+ throw null;
+ }
+}
+
+class D : C
+{
+ public override (int, int) M ()
+ {
+ throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8139: `D.M((int, int))': cannot change tuple element names when overriding inherited member `C.M((int, int))'
+// Line: 13
+
+class C
+{
+ public virtual void M ((int, int) arg)
+ {
+ }
+}
+
+class D : C
+{
+ public override void M ((int c, int d) arg)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8139: `D.Prop': cannot change return type tuple element names when overriding inherited member `C.Prop'
+// Line: 14
+
+class C
+{
+ public virtual (int a, int b) Prop {
+ get {
+ throw null;
+ }
+ }
+}
+
+class D : C
+{
+ public override (int c, int d) Prop {
+ get {
+ throw null;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8139: `D.M()': cannot change return type tuple element names when overriding inherited member `C.M()'
+// Line: 14
+
+class C
+{
+ public virtual (int a, int b) M ()
+ {
+ throw null;
+ }
+}
+
+class D : C
+{
+ public override (int c, int d) M ()
+ {
+ throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8141:
+// Line: 11
+
+public interface I<T>
+{
+ int this[T arg] { get; set; }
+}
+
+public class C : I<(int a, int b)>
+{
+ public int this[(int c, int d) arg] {
+ get {
+ return 1;
+ }
+ set {
+
+ }
+ }
+}
--- /dev/null
+// CS8141:
+// Line: 9
+
+public interface I<T>
+{
+ T Test ();
+}
+
+public class C : I<(int a, int b)>
+{
+ public (int c, int d) Test ()
+ {
+ return (1, 2);
+ }
+}
--- /dev/null
+// CS8142: A partial method declaration and partial method implementation must both use the same tuple element names
+// Line: 11
+
+partial class X
+{
+ partial void Foo ((int a, int b) arg);
+}
+
+partial class X
+{
+ partial void Foo ((int c, int d) arg)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8143: An expression tree cannot contain a tuple literal
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+ public static void Main ()
+ {
+ Expression<Func<object>> l = () => (-1, 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8144:
+// Line: 12
+
+using System;
+using System.Linq.Expressions;
+
+class X
+{
+ public static void Main ()
+ {
+ (byte b, short d) t = (0, 0);
+ Expression<Func<(int a, int aa)>> e = () => t;
+ }
+}
--- /dev/null
+// CS8181: Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead
+// Line: 8
+
+class C
+{
+ static void Main ()
+ {
+ var x = new (long, int) () {
+ Item1 = 1
+ };
+ }
+}
--- /dev/null
+// CS8199: The syntax `var (...)' as an lvalue is reserved
+// Line: 8
+
+class X
+{
+ public static void Main ()
+ {
+ var (x.a, y) = (1, 'g');
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8210: A tuple literal cannot not contain a value of type `void'
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = (1, Main ());
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8307: The first operand of an `as' operator may not be a tuple literal without a natural type
+// Line: 8
+
+class X
+{
+ public static void Main ()
+ {
+ var g = (1, Main) as object;
+ }
+}
\ No newline at end of file
# Operators
cs0457-2.cs
cs0457.cs
+
+cs8129.cs NO ERROR
+cs8141.cs
+cs8141-2.cs
+cs8144.cs
return System.Linq.Expressions.Expression.Assign (target_object, source_object);
}
+
protected virtual Expression ResolveConversions (ResolveContext ec)
{
source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location);
pe.SetBackingFieldAssigned (fc);
return;
}
+
+ var td = target as TupleDeconstruct;
+ if (td != null) {
+ td.SetGeneratedFieldAssigned (fc);
+ return;
+ }
}
public override Reachability MarkReachable (Reachability rc)
Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
}
+ public void Error_MisusedTupleAttribute ()
+ {
+ Report.Error (8138, loc, "Do not use `{0}' directly. Use the tuple syntax instead", GetSignatureForError ());
+ }
+
void Error_AttributeEmitError (string inner)
{
Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
}
if (!IsConditionallyExcluded (ctor.DeclaringType)) {
+ if (Type == predefined.TupleElementNames) {
+ Error_MisusedTupleAttribute ();
+ return;
+ }
+
try {
foreach (Attributable target in targets)
target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
// New in .NET 4.5
public readonly PredefinedStateMachineAttribute AsyncStateMachine;
+ // New in .NET 4.7
+ public readonly PredefinedTupleElementNamesAttribute TupleElementNames;
+
//
// Optional types which are used as types and for member lookup
//
CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
+ TupleElementNames = new PredefinedTupleElementNamesAttribute (module, "System.Runtime.CompilerServices", "TupleElementNamesAttribute");
+
// TODO: Should define only attributes which are used for comparison
const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
return tctor != null;
}
}
+
+ public class PredefinedTupleElementNamesAttribute : PredefinedAttribute
+ {
+ MethodSpec tctor;
+
+ public PredefinedTupleElementNamesAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
+ {
+ }
+
+ public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ CustomAttributeBuilder CreateCustomAttributeBuilder (TypeSpec type, Location loc)
+ {
+ if (tctor == null) {
+ tctor = module.PredefinedMembers.TupleElementNamesAttributeCtor.Resolve (loc);
+ if (tctor == null)
+ return null;
+ }
+
+ var names = new List<string> (type.TypeArguments.Length);
+ BuildStringElements (type, names);
+ return new CustomAttributeBuilder ((ConstructorInfo)tctor.GetMetaInfo (), new object [] { names.ToArray () });
+ }
+
+ //
+ // Returns an array of names when any element of the type is
+ // tuple with named element. The array is built for top level
+ // type therefore it can contain multiple tuple types
+ //
+ // Example: Func<(int, int), int, (int a, int b)[]>
+ // Output: { null, null, "a", "b" }
+ //
+ static void BuildStringElements (TypeSpec type, List<string> names)
+ {
+ while (type is ArrayContainer) {
+ type = ((ArrayContainer)type).Element;
+ }
+
+ var nts = type as NamedTupleSpec;
+ if (nts != null) {
+ names.AddRange (nts.Elements);
+ } else {
+ for (int i = 0; i < type.Arity; ++i) {
+ names.Add (null);
+ }
+ }
+
+ foreach (var ta in type.TypeArguments) {
+ BuildStringElements (ta, names);
+ }
+ }
+ }
}
public override void Emit ()
{
+ if (Interfaces != null) {
+ foreach (var iface in Interfaces) {
+ if (iface.HasNamedTupleElement) {
+ throw new NotImplementedException ("named tuples for .interfaceimpl");
+ }
+ }
+ }
+
if (OptAttributes != null)
OptAttributes.Emit ();
if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
- if (base_type != null && base_type.HasDynamicElement) {
- Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+ if (base_type != null) {
+ if (base_type.HasDynamicElement)
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+ if (base_type.HasNamedTupleElement)
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (TypeBuilder, base_type, Location);
}
}
ok = false;
}
- var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
+ var base_member_type = ((IInterfaceMemberSpec)base_member).MemberType;
if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
Report.SymbolRelatedToPreviousError (base_member);
if (this is PropertyBasedMember) {
GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
}
ok = false;
+ } else if (!NamedTupleSpec.CheckOverrideName (MemberType, base_member_type)) {
+ // CSC: Should be different error code
+ Report.Error (8139, Location, "`{0}': cannot change return type tuple element names when overriding inherited member `{1}'",
+ GetSignatureForError (), base_member.GetSignatureForError ());
+ ok = false;
+ }
+
+ var base_params = base_member as IParametersMember;
+ if (base_params != null) {
+ if (!NamedTupleSpec.CheckOverrideName ((IParametersMember)this, base_params)) {
+ Report.Error (8139, Location, "`{0}': cannot change tuple element names when overriding inherited member `{1}'",
+ GetSignatureForError (), base_member.GetSignatureForError ());
+ ok = false;
+ }
}
return ok;
return null;
}
+ static Expression ImplicitTupleLiteralConversion (ResolveContext rc, Expression source, TypeSpec targetType, Location loc)
+ {
+ var targetTypeArgument = targetType.TypeArguments;
+ if (source.Type.Arity != targetTypeArgument.Length)
+ return null;
+
+ var namedTarget = targetType as NamedTupleSpec;
+ var tupleLiteral = source as TupleLiteral;
+ Expression instance;
+
+ if (tupleLiteral == null && !ExpressionAnalyzer.IsInexpensiveLoad (source)) {
+ var expr_variable = LocalVariable.CreateCompilerGenerated (source.Type, rc.CurrentBlock, loc);
+ source = new CompilerAssign (expr_variable.CreateReferenceExpression (rc, loc), source, loc);
+ instance = expr_variable.CreateReferenceExpression (rc, loc);
+ } else {
+ instance = null;
+ }
+
+ var converted = new List<Expression> (targetType.Arity);
+ for (int i = 0; i < targetType.Arity; ++i) {
+ Expression elementSrc;
+ if (tupleLiteral != null) {
+ elementSrc = tupleLiteral.Elements [i].Expr;
+
+ if (namedTarget != null) {
+ var elementSrcName = tupleLiteral.Elements [i].Name;
+ if (elementSrcName != null && elementSrcName != namedTarget.Elements [i]) {
+ rc.Report.Warning (8123, 1, loc,
+ "The tuple element name `{0}' is ignored because a different name or no name is specified by the target type `{1}'",
+ elementSrcName, namedTarget.GetSignatureForErrorWithNames ());
+ }
+ }
+ } else {
+ elementSrc = new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)).Resolve (rc);
+ }
+
+ var res = ImplicitConversionStandard (rc, elementSrc, targetTypeArgument [i], loc);
+ if (res == null)
+ return null;
+
+ converted.Add (res);
+ }
+
+ return new TupleLiteralConversion (source, targetType, converted, loc);
+ }
+
+ static bool ImplicitTupleLiteralConversionExists (Expression source, TypeSpec targetType)
+ {
+ if (source.Type.Arity != targetType.Arity)
+ return false;
+
+ var srcTypeArgument = source.Type.TypeArguments;
+ var targetTypeArgument = targetType.TypeArguments;
+
+ var tupleLiteralElements = (source as TupleLiteral)?.Elements;
+
+ for (int i = 0; i < targetType.Arity; ++i) {
+ var elementType = srcTypeArgument [i];
+
+ if (tupleLiteralElements != null) {
+ if (!ImplicitStandardConversionExists (tupleLiteralElements[i].Expr, targetTypeArgument [i])) {
+ return false;
+ }
+ } else {
+ if (!ImplicitStandardConversionExists (new EmptyExpression (srcTypeArgument [i]), targetTypeArgument [i])) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
//
// Full version of implicit conversion
//
if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
return true;
-
+
+ if (expr_type.IsTupleType && target_type.IsTupleType)
+ return ImplicitTupleLiteralConversionExists (expr, target_type);
+
//
// Implicit Constant Expression Conversions
//
return c;
}
+ if (expr_type.IsTupleType) {
+ if (target_type.IsTupleType)
+ return ImplicitTupleLiteralConversion (ec, expr, target_type, loc);
+
+ if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (expr_type))
+ return null;
+ }
+
e = ImplicitNumericConversion (expr, expr_type, target_type);
if (e != null)
return e;
/// ImplicitConversion. If there is no implicit conversion, then
/// an error is signaled
/// </summary>
- static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
+ public static Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
TypeSpec target_type, Location loc)
{
Expression e = ImplicitConversion (ec, source, target_type, loc);
if (e != null)
return e;
- source.Error_ValueCannotBeConverted (ec, target_type, false);
+ if (target_type != InternalType.ErrorType)
+ source.Error_ValueCannotBeConverted (ec, target_type, false);
return null;
}
%token GENERIC_DIMENSION
%token DEFAULT_COLON
%token OPEN_BRACKET_EXPR
+%token OPEN_PARENS_DECONSTRUCT
// Make the parser go into eval mode parsing (statements and compilation units).
%token EVAL_STATEMENT_PARSER
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, Argument.AType.Out);
lbag.AddLocation ($$, GetLocation($2));
}
-
;
named_argument_expr
$$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2);
}
| builtin_type_expression
+ | OPEN_PARENS tuple_elements CLOSE_PARENS opt_nullable
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var a = (Tuple<TypeArguments, List<string>>) $2;
+ if (a.Item1.Count < 2) {
+ report.Error (8124, GetLocation ($1), "Tuple must contain at least two elements");
+ }
+
+ $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+
+ if ($4 != null)
+ $$ = new ComposedCast ((FullNamedExpression) $$, (ComposedTypeSpecifier) $4);
+ }
+ ;
+
+tuple_elements
+ : tuple_element tuple_element_name
+ {
+ var type_args = new TypeArguments ();
+ type_args.Add ((FullNamedExpression) $1);
+
+ var names = new List<string> (2);
+ var lt = (LocatedToken) $2;
+ names.Add (lt?.Value);
+
+ $$ = Tuple.Create (type_args, names);
+ }
+ | tuple_elements COMMA tuple_element tuple_element_name
+ {
+ var a = (Tuple<TypeArguments, List<string>>) $1;
+ a.Item1.Add ((FullNamedExpression) $3);
+ var lt = (LocatedToken) $4;
+ a.Item2.Add (lt?.Value);
+ $$ = a;
+ }
+ ;
+
+tuple_element_name
+ : /* empty */
+ | IDENTIFIER
+ ;
+
+tuple_element
+ : parameter_type
;
void_invalid
literal
: boolean_literal
+ | tuple_literal
| LITERAL
| NULL { $$ = new NullLiteral (GetLocation ($1)); }
;
| FALSE { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); }
;
+tuple_literal
+ : OPEN_PARENS tuple_literal_elements CLOSE_PARENS
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ $$ = new TupleLiteral ((List<TupleLiteralElement>)$2, GetLocation ($1));
+ }
+ ;
+
+tuple_literal_elements
+ : tuple_literal_element COMMA tuple_literal_element
+ {
+ $$ = new List<TupleLiteralElement> () {
+ (TupleLiteralElement) $1, (TupleLiteralElement) $3
+ };
+ }
+ | tuple_literal_elements COMMA tuple_literal_element
+ {
+ var list = (List<TupleLiteralElement>)$1;
+ list.Add ((TupleLiteralElement) $3);
+ }
+ ;
+
+tuple_literal_element
+ : expression
+ {
+ $$ = new TupleLiteralElement ((Expression) $1);
+ }
+ | IDENTIFIER COLON expression
+ {
+ var lt = (LocatedToken) $1;
+ $$ = new TupleLiteralElement (lt.Value, (Expression) $3, lt.Location);
+ }
+ ;
+
interpolated_string
: INTERPOLATED_STRING interpolations INTERPOLATED_STRING_END
{
$$ = new Unary (Unary.Operator.AddressOf, null, GetLocation ($1));
}
- ;
multiplicative_expression
: prefixed_unary_expression
{
$$ = new WildcardPattern (GetLocation ($1));
}
- | pattern_expr_invocation
+/* | pattern_expr_invocation */
| pattern_property
;
+/*
pattern_expr_invocation
: type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS
{
$$ = new RecursivePattern ((ATypeNameExpression) $1, (Arguments) $3, GetLocation ($2));
}
;
+*/
pattern_property
: type_name_expression OPEN_BRACE pattern_property_list CLOSE_BRACE
}
;
+/*
opt_pattern_list
- : /* empty */
+ : // empty
{
$$ = new Arguments (0);
}
}
;
+
pattern_argument
: pattern
{
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3);
}
;
+*/
shift_expression
: additive_expression
$$ = new CompoundAssign (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3);
lbag.AddLocation ($$, GetLocation ($2));
}
+ | OPEN_PARENS_DECONSTRUCT deconstruct_exprs CLOSE_PARENS ASSIGN expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var exprs = (List<Expression>) $2;
+ $$ = new TupleDeconstruct (exprs, (Expression) $5, GetLocation ($4));
+ }
+ ;
+
+deconstruct_exprs
+ : expression COMMA expression
+ {
+ $$ = new List<Expression> () {
+ (Expression) $1,
+ (Expression) $3
+ };
+ }
+ | deconstruct_exprs COMMA expression
+ {
+ var src = (List<Expression>) $1;
+ src.Add ((Expression) $3);
+ $$ = src;
+ }
;
lambda_parameter_list
variable_type_simple
: type_name_expression opt_nullable
{
- // Ok, the above "primary_expression" is there to get rid of
- // both reduce/reduce and shift/reduces in the grammar, it should
- // really just be "type_name". If you use type_name, a reduce/reduce
- // creeps up. If you use namespace_or_type_name (which is all we need
- // really) two shift/reduces appear.
- //
-
- // So the super-trick is that primary_expression
- // can only be either a SimpleName or a MemberAccess.
- // The MemberAccess case arises when you have a fully qualified type-name like :
- // Foo.Bar.Blah i;
- // SimpleName is when you have
- // Blah i;
-
var expr = (ATypeNameExpression) $1;
if ($2 == null) {
if (expr.Name == "var" && expr is SimpleName)
$$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2);
}
| builtin_type_expression
+ | tuple_type opt_nullable
+ {
+ if ($2 == null)
+ $$ = $1;
+ else
+ $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2);
+ }
| void_invalid
;
-
+
+tuple_type
+ : OPEN_PARENS tuple_type_elements CLOSE_PARENS
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var a = (Tuple<TypeArguments, List<string>>) $2;
+
+ $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+ }
+ ;
+
+tuple_type_elements
+ : variable_type IDENTIFIER /* opt_identifier */ COMMA variable_type IDENTIFIER /* opt_identifier */
+ {
+ var type_args = new TypeArguments ();
+
+ type_args.Add ((FullNamedExpression) $1);
+ type_args.Add ((FullNamedExpression) $4);
+
+ var names = new List<string> (2);
+ var lt = (LocatedToken) $2;
+ names.Add (lt?.Value);
+ lt = (LocatedToken) $5;
+ names.Add (lt?.Value);
+
+ $$ = Tuple.Create (type_args, names);
+ }
+ | tuple_type_elements COMMA variable_type IDENTIFIER /* opt_identifier */
+ {
+ var a = (Tuple<TypeArguments, List<string>>) $1;
+ a.Item1.Add ((FullNamedExpression) $3);
+ var lt = (LocatedToken) $4;
+ a.Item2.Add (lt?.Value);
+ $$ = a;
+ }
+ ;
+
pointer_stars
: pointer_star
| pointer_star pointer_stars
return "]";
case Token.OPEN_PARENS_CAST:
case Token.OPEN_PARENS_LAMBDA:
+ case Token.OPEN_PARENS_DECONSTRUCT:
case Token.OPEN_PARENS:
return "(";
case Token.CLOSE_PARENS:
}
//
- // Open parens micro parser. Detects both lambda and cast ambiguity.
+ // Open parens micro parser
//
int TokenizeOpenParens ()
{
int bracket_level = 0;
bool is_type = false;
bool can_be_type = false;
+ bool at_least_one_comma = false;
while (true) {
ptoken = current_token;
if (current_token == Token.ARROW)
return Token.OPEN_PARENS_LAMBDA;
+ //
+ // Expression inside parens is deconstruct expression, (a, x.y) = ...
+ //
+ if (current_token == Token.ASSIGN && at_least_one_comma)
+ return Token.OPEN_PARENS_DECONSTRUCT;
+
//
// Expression inside parens is single type, (int[])
//
if (bracket_level == 0) {
bracket_level = 100;
can_be_type = is_type = false;
+ at_least_one_comma = true;
}
continue;
}
return false;
+ case Token.OPEN_PARENS:
+ if (!parsing_generic_declaration)
+ return false;
+
+ while (true) {
+ switch (token ()) {
+ case Token.COMMA:
+ // tuple declaration after <
+ return true;
+ case Token.OP_GENERICS_GT:
+ case Token.EOF:
+ return false;
+ }
+ }
+
default:
return false;
}
case Token.DEFAULT:
case Token.DELEGATE:
case Token.OP_GENERICS_GT:
+ case Token.REFVALUE:
return Token.OPEN_PARENS;
}
MissingDependency = 1 << 5,
HasDynamicElement = 1 << 6,
ConstraintsChecked = 1 << 7,
+ HasNamedTupleElement = 1 << 8,
IsAccessor = 1 << 9, // Method is an accessor
IsGeneric = 1 << 10, // Member contains type arguments
GenericIterateInterface = 1 << 21,
GenericTask = 1 << 22,
InterfacesImported = 1 << 23,
+ Tuple = 1 << 24
}
//
StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected |
StateFlags.Obsolete | StateFlags.Obsolete_Undetected |
StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected |
- StateFlags.HasDynamicElement;
+ StateFlags.HasDynamicElement | StateFlags.HasNamedTupleElement;
protected Modifiers modifiers;
public StateFlags state;
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Target == AttributeTargets.ReturnValue) {
- if (return_attributes == null)
- return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
-
+ CreateReturnBuilder ();
return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
}
}
+ ReturnParameter CreateReturnBuilder ()
+ {
+ return return_attributes ?? (return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location));
+ }
+
protected override bool DoDefineMembers ()
{
var builtin_types = Compiler.BuiltinTypes;
}
}
- if (ReturnType.Type != null) {
- if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
- } else if (ReturnType.Type.HasDynamicElement) {
- return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType.Type, Location);
+ var rtype = ReturnType.Type;
+ if (rtype != null) {
+ if (rtype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
+ } else if (rtype.HasDynamicElement) {
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, rtype, Location);
+ }
+
+ if (rtype.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, rtype, Location);
}
ConstraintChecker.Check (this, ReturnType.Type, ReturnType.Location);
PropertyAccess,
EventAccess,
IndexerAccess,
- Nothing,
+ Nothing,
}
/// <remarks>
return MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
}
+ if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+ var ntuple = queried_type as NamedTupleSpec;
+ if (ntuple != null) {
+ var ms = ntuple.FindElement (rc, name, loc);
+ if (ms != null)
+ return ExprClassFromMemberInfo (ms, loc);
+ }
+ }
+
return null;
}
{
}
- public bool InferType (ResolveContext ec, Expression right_side)
+ public bool InferType (ResolveContext ec, Expression rhs)
{
if (type != null)
throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
- type = right_side.Type;
- if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
+ type = rhs.Type;
+
+ if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || (rhs is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
ec.Report.Error (815, loc,
"An implicitly typed local variable declaration cannot be initialized with `{0}'",
type.GetSignatureForError ());
eclass = ExprClass.Value;
TypeSpec etype = expr.Type;
+ if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (etype)) {
+ ec.Report.Error (8307, expr.Location, "The first operand of an `as' operator may not be a tuple literal without a natural type");
+ type = InternalType.ErrorType;
+ return this;
+ }
+
if (type == null) {
type = InternalType.ErrorType;
return this;
return DoResolveInvocation (rc);
}
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+ {
+ var sn = expr as SimpleName;
+ if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
+ var targets = new List<Expression> (arguments.Count);
+ var variables = new List<LocalVariable> (arguments.Count);
+ foreach (var arg in arguments) {
+ var arg_sn = arg.Expr as SimpleName;
+ if (arg_sn == null || arg_sn.Arity != 0) {
+ rc.Report.Error (8199, loc, "The syntax `var (...)' as an lvalue is reserved");
+ return ErrorExpression.Instance;
+ }
+
+ var lv = new LocalVariable (rc.CurrentBlock, arg_sn.Name, arg.Expr.Location);
+ rc.CurrentBlock.AddLocalName (lv);
+ variables.Add (lv);
+
+ targets.Add (new LocalVariableReference (lv, arg_sn.Location));
+ }
+
+ var res = new TupleDeconstruct (targets, variables, right_side, loc);
+ return res.Resolve (rc);
+ }
+
+ return base.DoResolveLValue (rc, right_side);
+ }
+
Expression DoResolveInvocation (ResolveContext ec)
{
Expression member_expr;
protected override Expression DoResolve (ResolveContext ec)
{
+ if (RequestedType is TupleTypeExpr) {
+ ec.Report.Error (8181, loc, "Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead.");
+ }
+
type = RequestedType.ResolveAsType (ec);
if (type == null)
return null;
array_element_type = best_type_inference.InferredTypeArguments[0];
best_type_inference = null;
- if (array_element_type == null ||
- array_element_type == InternalType.NullLiteral || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
- arguments.Count != rank.Dimension) {
+ if (array_element_type == null || InternalType.HasNoType (array_element_type) || arguments.Count != rank.Dimension) {
ec.Report.Error (826, loc,
"The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
return null;
}
type = e.Type;
- if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
+ if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || type.IsPointer || (e is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
Error_InvalidInitializer (ec, type.GetSignatureForError ());
return null;
}
Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location);
}
+ if (member_type.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (FieldBuilder, member_type, Location);
+ }
+
if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder);
if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
}
}
-#endregion
+ #endregion
public FieldInfo GetMetaInfo ()
{
foreach (var arg in targs) {
if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
state |= StateFlags.HasDynamicElement;
- break;
+ }
+
+ if (arg.HasNamedTupleElement) {
+ state |= StateFlags.HasNamedTupleElement;
}
}
}
}
+ public override bool IsTupleType {
+ get {
+ return (open_type.state & StateFlags.Tuple) != 0;
+ }
+ }
+
//
// Types used to inflate the generic type
//
bound.Type == InternalType.ThrowExpr)
return;
+ if (bound.Type.IsTupleType && TupleLiteral.ContainsNoTypeElement (bound.Type))
+ return;
+
var a = bounds [index];
if (a == null) {
a = new List<BoundInfo> (2);
if (t.Name[0] == '<')
continue;
- var it = CreateType (t, null, new DynamicTypeReader (t), true);
+ var it = CreateType (t, null, new AttributesTypeInfoReader (t), true);
if (it == null)
continue;
public abstract class MetadataImporter
{
//
- // Dynamic types reader with additional logic to reconstruct a dynamic
- // type using DynamicAttribute values
+ // Types reader with additional logic to reconstruct extra
+ // type information encoded in custom attributes values
//
- protected struct DynamicTypeReader
+ protected struct AttributesTypeInfoReader
{
static readonly bool[] single_attribute = { true };
- public int Position;
- bool[] flags;
+ public int DynamicPosition;
+ bool[] dynamicFlags;
+
+ public int TuplePosition;
+ string[] tupleNames;
// There is no common type for CustomAttributeData and we cannot
// use ICustomAttributeProvider
//
// A member provider which can be used to get CustomAttributeData
//
- public DynamicTypeReader (object provider)
+ public AttributesTypeInfoReader (object provider)
{
- Position = 0;
- flags = null;
+ DynamicPosition = 0;
+ TuplePosition = 0;
+ dynamicFlags = null;
+ tupleNames = null;
this.provider = provider;
}
if (provider != null)
ReadAttribute ();
- return flags != null && Position < flags.Length && flags[Position];
+ return dynamicFlags != null && DynamicPosition < dynamicFlags.Length && dynamicFlags [DynamicPosition];
}
//
if (provider != null)
ReadAttribute ();
- return flags != null;
+ return dynamicFlags != null;
+ }
+
+ public bool HasNamedTupleAttribute ()
+ {
+ if (provider != null)
+ ReadAttribute ();
+
+ return tupleNames != null;
+ }
+
+ public IList<string> GetNamedTupleElements (int length)
+ {
+ if (TuplePosition == 0 && length == tupleNames.Length)
+ return tupleNames;
+
+ for (int i = TuplePosition; i < length + TuplePosition; ++i) {
+ if (tupleNames [i] != null) {
+ var res = new string [length];
+ Array.Copy (tupleNames, TuplePosition, res, 0, length);
+ return res;
+ }
+ }
+
+ //
+ // Current range can be just padding
+ //
+ return null;
}
IList<CustomAttributeData> GetCustomAttributes ()
if (cad.Count > 0) {
foreach (var ca in cad) {
var dt = ca.Constructor.DeclaringType;
- if (dt.Name != "DynamicAttribute" || dt.Namespace != CompilerServicesNamespace)
+ if (dt.Namespace != CompilerServicesNamespace)
continue;
- if (ca.ConstructorArguments.Count == 0) {
- flags = single_attribute;
- break;
- }
+ switch (dt.Name) {
+ case "DynamicAttribute":
+ if (ca.ConstructorArguments.Count == 0) {
+ dynamicFlags = single_attribute;
+ break;
+ }
- var arg_type = ca.ConstructorArguments[0].ArgumentType;
+ var arg_type = ca.ConstructorArguments [0].ArgumentType;
- if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
- var carg = (IList<CustomAttributeTypedArgument>) ca.ConstructorArguments[0].Value;
- flags = new bool[carg.Count];
- for (int i = 0; i < flags.Length; ++i) {
- if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean)
- flags[i] = (bool) carg[i].Value;
+ if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
+ var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+ dynamicFlags = new bool [carg.Count];
+ for (int i = 0; i < dynamicFlags.Length; ++i) {
+ if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.Boolean)
+ dynamicFlags [i] = (bool)carg [i].Value;
+ }
+ }
+
+ break;
+ case "TupleElementNamesAttribute":
+ if (ca.ConstructorArguments.Count != 1)
+ break;
+
+ var tuple_arg_type = ca.ConstructorArguments [0].ArgumentType;
+ if (tuple_arg_type.IsArray && MetaType.GetTypeCode (tuple_arg_type.GetElementType ()) == TypeCode.String) {
+ var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+ tupleNames = new string [carg.Count];
+ for (int i = 0; i < tupleNames.Length; ++i) {
+ if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.String)
+ tupleNames [i] = (string)carg [i].Value;
+ }
}
break;
TypeSpec field_type;
try {
- field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi), declaringType);
+ field_type = ImportType (fi.FieldType, new AttributesTypeInfoReader (fi), declaringType);
//
// Private field has private type which is not fixed buffer
if (add.Modifiers != remove.Modifiers)
throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
- var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei), declaringType);
+ var event_type = ImportType (ei.EventHandlerType, new AttributesTypeInfoReader (ei), declaringType);
var definition = new ImportedMemberDefinition (ei, event_type, this);
return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove);
}
var type = tparams[pos];
int index = pos - first;
- tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false);
+ tspec[index] = (TypeParameterSpec) CreateType (type, new AttributesTypeInfoReader (), false);
}
return tspec;
}
- TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype)
+ TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, AttributesTypeInfoReader dtype)
{
- ++dtype.Position;
+ ++dtype.DynamicPosition;
var tspec = new TypeSpec [tparams.Length - first];
for (int pos = first; pos < tparams.Length; ++pos) {
TypeSpec spec;
if (type.HasElementType) {
var element = type.GetElementType ();
- ++dtype.Position;
+ ++dtype.DynamicPosition;
spec = ImportType (element, dtype, null);
if (!type.IsArray) {
if (spec == null)
return null;
- ++dtype.Position;
+ ++dtype.DynamicPosition;
tspec[index] = spec;
}
returnType = module.Compiler.BuiltinTypes.Void;
} else {
var mi = (MethodInfo)mb;
- returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter), declaringType);
+ returnType = ImportType (mi.ReturnType, new AttributesTypeInfoReader (mi.ReturnParameter), declaringType);
//
// Detect operators and destructors
// Strip reference wrapping
//
var el = p.ParameterType.GetElementType ();
- types[i] = ImportType (el, new DynamicTypeReader (p), parent); // TODO: 1-based positio to be csc compatible
+ types[i] = ImportType (el, new AttributesTypeInfoReader (p), parent); // TODO: 1-based positio to be csc compatible
} else if (i == 0 && method.IsStatic && (parent.Modifiers & Modifiers.METHOD_EXTENSION) != 0 &&
HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
mod = Parameter.Modifier.This;
- types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+ types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
} else {
- types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+ types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
public TypeSpec CreateType (MetaType type)
{
- return CreateType (type, new DynamicTypeReader (), true);
+ return CreateType (type, new AttributesTypeInfoReader (), true);
}
public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType)
{
- return CreateType (type, declaringType, new DynamicTypeReader (type), false);
+ return CreateType (type, declaringType, new AttributesTypeInfoReader (type), false);
}
- TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType)
+ TypeSpec CreateType (MetaType type, AttributesTypeInfoReader dtype, bool canImportBaseType)
{
TypeSpec declaring_type;
if (type.IsNested && !type.IsGenericParameter)
- declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true);
+ declaring_type = CreateType (type.DeclaringType, new AttributesTypeInfoReader (type.DeclaringType), true);
else
declaring_type = null;
return CreateType (type, declaring_type, dtype, canImportBaseType);
}
- protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType)
+ protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, AttributesTypeInfoReader dtype, bool canImportBaseType)
{
TypeSpec spec;
if (import_cache.TryGetValue (type, out spec)) {
return null;
if (declaringType == null) {
// Simple case, no nesting
- spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
+ spec = CreateType (type_def, null, new AttributesTypeInfoReader (), canImportBaseType);
spec = spec.MakeGenericType (module, targs);
} else {
//
}
}
+ if (spec.IsTupleType && dtype.HasNamedTupleAttribute ()) {
+ var names = dtype.GetNamedTupleElements (spec.Arity);
+ if (names != null)
+ return NamedTupleSpec.MakeType (module, (InflatedTypeSpec) spec, names);
+
+ dtype.TuplePosition += spec.Arity;
+ }
+
// Don't add generic type with dynamic arguments, they can interfere with same type
// using object type arguments
if (!spec.HasDynamicElement) {
else if (type.BaseType != null) {
TypeSpec base_type;
if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType)
- base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true);
+ base_type = CreateType (type.BaseType, new AttributesTypeInfoReader (type), true);
else
base_type = CreateType (type.BaseType);
if (t.Name[0] == '<')
continue;
- var it = CreateType (t, null, new DynamicTypeReader (t), true);
+ var it = CreateType (t, null, new AttributesTypeInfoReader (t), true);
if (it == null)
continue;
public TypeSpec ImportType (MetaType type)
{
- return ImportType (type, new DynamicTypeReader (type), null);
+ return ImportType (type, new AttributesTypeInfoReader (type), null);
}
- TypeSpec ImportType (MetaType type, DynamicTypeReader dtype, TypeSpec currentType)
+ TypeSpec ImportType (MetaType type, AttributesTypeInfoReader dtype, TypeSpec currentType)
{
if (type.HasElementType) {
var element = type.GetElementType ();
- ++dtype.Position;
+ ++dtype.DynamicPosition;
var spec = ImportType (element, dtype, currentType);
if (type.IsArray)
<Compile Include="settings.cs" />\r
<Compile Include="statement.cs" />\r
<Compile Include="support.cs" />\r
+ <Compile Include="tuples.cs" />\r
<Compile Include="typemanager.cs" />\r
<Compile Include="typespec.cs" />\r
<Compile Include="visit.cs" />\r
<Compile Include="field.cs" />\r
<Compile Include="typespec.cs" />\r
<Compile Include="visit.cs" />\r
+ <Compile Include="tuples.cs" />\r
</ItemGroup>\r
<ItemGroup Label="IKVM.Reflection">\r
<Compile Include="..\..\external\ikvm\reflect\*.cs">\r
support.cs
typemanager.cs
typespec.cs
+tuples.cs
visit.cs
../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
}
return false;
}
+
+ var pm_member = (MethodCore)member;
+ if (!NamedTupleSpec.CheckOverrideName (pm, pm_member) || !NamedTupleSpec.CheckOverrideName (pm.MemberType, pm_member.MemberType)) {
+ Report.Error (8142, member.Location,
+ "A partial method declaration and partial method implementation must both use the same tuple element names");
+ }
}
}
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Target == AttributeTargets.ReturnValue) {
- if (return_attributes == null)
- return_attributes = new ReturnParameter (this, MethodBuilder, Location);
-
- return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
+ CreateReturnBuilder ().ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
return new EmitContext (this, ig, MemberType, sourceMethod);
}
+ ReturnParameter CreateReturnBuilder ()
+ {
+ return return_attributes ?? (return_attributes = new ReturnParameter (this, MethodBuilder, Location));
+ }
+
public override bool Define ()
{
if (!base.Define ())
explicit_name = null;
} else {
- MethodData = new MethodData (this, ModFlags, flags, this, base_method);
+ MethodData = new MethodData (this, ModFlags, flags, this);
if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
return false;
Module.PredefinedAttributes.DebuggerStepThrough.EmitAttribute (MethodBuilder);
if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- return_attributes = new ReturnParameter (this, MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
} else if (ReturnType.HasDynamicElement) {
- return_attributes = new ReturnParameter (this, MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
+ }
+
+ if (ReturnType.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
}
if (OptAttributes != null)
protected Modifiers modifiers;
protected MethodAttributes flags;
protected TypeSpec declaring_type;
- protected MethodSpec parent_method;
SourceMethodBuilder debug_builder;
string full_name;
this.method = method;
}
- public MethodData (InterfaceMemberBase member,
- Modifiers modifiers, MethodAttributes flags,
- IMethodData method,
- MethodSpec parent_method)
- : this (member, modifiers, flags, method)
- {
- this.parent_method = parent_method;
- }
-
public bool Define (TypeDefinition container, string method_full_name)
{
PendingImplementation pending = container.PendingImplementations;
}
}
}
+
+ if (!NamedTupleSpec.CheckOverrideName (member.MemberType, implementing.ReturnType)) {
+ container.Compiler.Report.Error (8141, method.Location,
+ "The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
+ member.GetSignatureForError (), implementing.GetSignatureForError ());
+ }
+
+ var p_member = method as IParametersMember;
+ var p_implementing = implementing as IParametersMember;
+ if (p_member != null && p_implementing != null && !NamedTupleSpec.CheckOverrideName (p_member, p_implementing)) {
+ container.Compiler.Report.Error (8141, method.Location,
+ "The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
+ member.GetSignatureForError (), implementing.GetSignatureForError ());
+ }
}
}
} else {
}
} else {
//
- // Setting implementin to null inside this block will trigger a more
+ // Setting implementing to null inside this block will trigger a more
// verbose error reporting for missing interface implementations
//
if (implementing.DeclaringType.IsInterface) {
}
if (a.Target == AttributeTargets.ReturnValue) {
- if (return_attributes == null)
- return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
-
+ CreateReturnBuilder ();
return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
throw new NotSupportedException ();
}
+ ReturnParameter CreateReturnBuilder ()
+ {
+ return return_attributes ?? (return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location));
+ }
+
public virtual void Emit (TypeDefinition parent)
{
method_data.Emit (parent);
Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
} else if (ReturnType.HasDynamicElement) {
- return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
+ }
+
+ if (ReturnType.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
}
if (OptAttributes != null)
} else if (parameter_type.HasDynamicElement) {
pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
}
+
+ if (parameter_type.HasNamedTupleElement) {
+ pa.TupleElementNames.EmitAttribute (builder, parameter_type, Location);
+ }
}
}
Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
}
+ if (member_type.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (PropertyBuilder, member_type, Location);
+ }
+
ConstraintChecker.Check (this, member_type, type_expr.Location);
first.Emit (Parent);
3021, 3022, 3023, 3024, 3026, 3027,
4014, 4024, 4025, 4026,
7035, 7080, 7081, 7082, 7095,
- 8009, 8094
+ 8009, 8094, 8123
};
public Report (CompilerContext context, ReportPrinter printer)
--- /dev/null
+//
+// tuples.cs: Tuples types
+//
+// Author:
+// Marek Safar (marek.safar@gmail.com)
+//
+// Dual licensed under the terms of the MIT X11 or GNU GPL
+//
+// Copyright (C) Microsoft Corporation.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Globalization;
+
+#if STATIC
+using MetaType = IKVM.Reflection.Type;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using MetaType = System.Type;
+using System.Reflection;
+using System.Reflection.Emit;
+#endif
+
+namespace Mono.CSharp
+{
+ class TupleTypeExpr : TypeExpr
+ {
+ TypeArguments elements;
+ List<string> names;
+
+ public TupleTypeExpr (TypeArguments elements, List<string> names, Location loc)
+ {
+ this.elements = elements;
+ this.names = names;
+ this.loc = loc;
+ }
+
+ public override TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
+ {
+ var length = elements.Count;
+ if (length > 7)
+ throw new NotImplementedException ("tuples > 7");
+
+ eclass = ExprClass.Type;
+
+ var otype = mc.Module.PredefinedTypes.Tuples [length - 1].Resolve ();
+ if (otype == null)
+ return null;
+
+ GenericTypeExpr ctype = new GenericTypeExpr (otype, elements, loc);
+ type = ctype.ResolveAsType (mc);
+
+ if (names != null && CheckElementNames (mc) && type != null) {
+ type = NamedTupleSpec.MakeType (mc.Module, (InflatedTypeSpec) type, names);
+ }
+
+ return type;
+ }
+
+ bool CheckElementNames (IMemberContext mc)
+ {
+ int first_name = -1;
+ for (int i = 0; i < names.Count; ++i) {
+ var name = names [i];
+ if (name == null)
+ continue;
+
+ if (IsReservedName (name)) {
+ mc.Module.Compiler.Report.Error (8126, loc, "The tuple element name `{0}' is reserved", name);
+ names [i] = null;
+ continue;
+ }
+
+ if (name.StartsWith ("Item", StringComparison.Ordinal)) {
+ var idx = name.Substring (4);
+ uint value;
+ if (uint.TryParse (idx, NumberStyles.Integer, CultureInfo.InvariantCulture, out value) && value != i + 1) {
+ mc.Module.Compiler.Report.Error (8125, loc, "The tuple element name `{0}' can only be used at position {1}", name, idx);
+ names [i] = null;
+ continue;
+ }
+ }
+
+ if (first_name < 0) {
+ first_name = i;
+ continue;
+ }
+
+ for (int ii = first_name; ii < i; ++ii) {
+ if (name == names [ii]) {
+ mc.Module.Compiler.Report.Error (8127, loc, "The tuple element name `{0}' is a duplicate", name);
+ names [i] = null;
+ break;
+ }
+ }
+ }
+
+ return first_name >= 0;
+ }
+
+ static bool IsReservedName (string name)
+ {
+ switch (name) {
+ case "CompareTo":
+ case "Deconstruct":
+ case "Equals":
+ case "GetHashCode":
+ case "Rest":
+ case "ToString":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override string GetSignatureForError ()
+ {
+ var sb = new StringBuilder ();
+ for (int i = 0; i < elements.Count; ++i) {
+ sb.Append (elements.Arguments [i].GetSignatureForError ());
+
+ if (names [i] != null) {
+ sb.Append (" ");
+ sb.Append (names [i]);
+ }
+
+ if (i != 0)
+ sb.Append (",");
+ }
+
+ return sb.ToString ();
+ }
+ }
+
+ public class NamedTupleSpec : TypeSpec
+ {
+ InflatedTypeSpec tuple;
+ IList<string> elements;
+
+ private NamedTupleSpec (InflatedTypeSpec tupleDefinition, IList<string> elements)
+ : base (tupleDefinition.Kind, tupleDefinition.DeclaringType, tupleDefinition.MemberDefinition, null, tupleDefinition.Modifiers)
+ {
+ tuple = tupleDefinition;
+ this.elements = elements;
+
+ state |= StateFlags.HasNamedTupleElement | StateFlags.Tuple;
+ }
+
+ public IList<string> Elements {
+ get {
+ return elements;
+ }
+ }
+
+ public override TypeSpec [] TypeArguments {
+ get {
+ return tuple.TypeArguments;
+ }
+ }
+
+ protected override void InitializeMemberCache (bool onlyTypes)
+ {
+ cache = tuple.MemberCache;
+ }
+
+ public override MetaType GetMetaInfo ()
+ {
+ return tuple.GetMetaInfo ();
+ }
+
+ public MemberSpec FindElement (IMemberContext mc, string name, Location loc)
+ {
+ // TODO: cache it
+ for (int i = 0; i < elements.Count; ++i) {
+ var ename = elements [i];
+ if (ename == null || ename != name)
+ continue;
+
+ var member_name = GetElementPropertyName (i);
+ var ms = MemberCache.FindMember (tuple, MemberFilter.Field (member_name, null), BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly);
+ if (ms == null) {
+ mc.Module.Compiler.Report.Error (8128, loc, "Member `{0}' was not found on type '{1}'", member_name, tuple.GetSignatureForError ());
+ return null;
+ }
+
+ return ms;
+ }
+
+ return null;
+ }
+
+ public override string GetSignatureForError ()
+ {
+ //
+ // csc reports names as well but it seems to me redundant when
+ // they are not included in any type conversion
+ //
+ return tuple.GetSignatureForError ();
+ }
+
+ public string GetSignatureForErrorWithNames ()
+ {
+ // TODO: Include names
+ return tuple.GetSignatureForError ();
+ }
+
+ public static NamedTupleSpec MakeType (ModuleContainer module, InflatedTypeSpec tupleType, IList<string> names)
+ {
+ // TODO: cache it
+ return new NamedTupleSpec (tupleType, names);
+ }
+
+ public static string GetElementPropertyName (int index)
+ {
+ return "Item" + (index + 1).ToString (CultureInfo.InvariantCulture);
+ }
+
+ public static bool CheckOverrideName (IParametersMember member, IParametersMember baseMember)
+ {
+ var btypes = baseMember.Parameters.Types;
+ var ttypes = member.Parameters.Types;
+ for (int ii = 0; ii < baseMember.Parameters.Count; ++ii) {
+ if (!CheckOverrideName (ttypes [ii], btypes [ii])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool CheckOverrideName (TypeSpec type, TypeSpec baseType)
+ {
+ var btype_ntuple = baseType as NamedTupleSpec;
+ var mtype_ntupe = type as NamedTupleSpec;
+ if (btype_ntuple == null && mtype_ntupe == null)
+ return true;
+
+ if (btype_ntuple != null || mtype_ntupe != null)
+ return false;
+
+ var b_elements = btype_ntuple.elements;
+ var m_elements = mtype_ntupe.elements;
+ for (int i = 0; i < b_elements.Count; ++i) {
+ if (b_elements [i] != m_elements [i])
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ class TupleLiteralElement
+ {
+ public TupleLiteralElement (string name, Expression expr, Location loc)
+ {
+ this.Name = name;
+ this.Expr = expr;
+ this.Location = loc;
+ }
+
+ public TupleLiteralElement (Expression expr)
+ {
+ this.Expr = expr;
+ this.Location = expr.Location;
+ }
+
+ public string Name { get; private set; }
+ public Expression Expr { get; set; }
+ public Location Location { get; private set; }
+ }
+
+ sealed class TupleLiteral : Expression
+ {
+ List<TupleLiteralElement> elements;
+
+ public TupleLiteral (List<TupleLiteralElement> elements, Location loc)
+ {
+ this.elements = elements;
+ this.loc = loc;
+ }
+
+ public List<TupleLiteralElement> Elements {
+ get {
+ return elements;
+ }
+ }
+
+ public static bool ContainsNoTypeElement (TypeSpec type)
+ {
+ var ta = type.TypeArguments;
+
+ for (int i = 0; i < ta.Length; ++i) {
+ var et = ta [i];
+ if (InternalType.HasNoType (et))
+ return true;
+
+ if (et.IsTupleType && ContainsNoTypeElement (et))
+ return true;
+ }
+
+ return false;
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext rc)
+ {
+ rc.Report.Error (8143, loc, "An expression tree cannot contain a tuple literal");
+ return ErrorExpression.Instance;
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ var ta = new TypeArguments ();
+ List<string> names = null;
+
+ for (int i = 0; i < elements.Count; ++i) {
+ var el = elements [i];
+ var expr = el.Expr.Resolve (rc);
+ if (expr == null) {
+ el.Expr = null;
+ ta = null;
+ continue;
+ }
+
+ if (expr.Type.Kind == MemberKind.Void) {
+ rc.Report.Error (8210, expr.Location, "A tuple literal cannot not contain a value of type `{0}'", expr.Type.GetSignatureForError ());
+ expr = null;
+ ta = null;
+ continue;
+ }
+
+ if (el.Name != null) {
+ if (names == null) {
+ names = new List<string> ();
+ for (int ii = 0; ii < i; ++ii) {
+ names.Add (null);
+ }
+ }
+
+ names.Add (el.Name);
+ }
+
+ el.Expr = expr;
+
+ if (ta != null)
+ ta.Add (new TypeExpression (expr.Type, expr.Location));
+ }
+
+ eclass = ExprClass.Value;
+
+ if (ta == null)
+ return null;
+
+ var t = new TupleTypeExpr (ta, names, loc);
+ type = t.ResolveAsType (rc) ?? InternalType.ErrorType;
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ foreach (var el in elements) {
+ el.Expr.Emit (ec);
+ }
+
+ // TODO: Needs arguments check
+ var ctor = MemberCache.FindMember (type, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly) as MethodSpec;
+
+ ec.Emit (OpCodes.Newobj, ctor);
+ }
+
+ public override void Error_ValueCannotBeConverted (ResolveContext rc, TypeSpec target, bool expl)
+ {
+ rc.Report.Error (8135, Location, "Tuple literal `{0}' cannot be converted to type `{1}'", type.GetSignatureForError (), target.GetSignatureForError ());
+ }
+ }
+
+ //
+ // Used when converting from a tuple literal or tuple instance to different tuple type
+ //
+ class TupleLiteralConversion : Expression
+ {
+ List<Expression> elements;
+ Expression source;
+
+ public TupleLiteralConversion (Expression source, TypeSpec type, List<Expression> elements, Location loc)
+ {
+ this.source = source;
+ this.type = type;
+ this.elements = elements;
+ this.loc = loc;
+
+ eclass = source.eclass;
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext rc)
+ {
+ rc.Report.Error (8144, loc, "An expression tree cannot contain a tuple conversion");
+ return null;
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ // Should not be reached
+ throw new NotSupportedException ();
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ if (!(source is TupleLiteral)) {
+ var assign = source as CompilerAssign;
+ if (assign != null)
+ assign.EmitStatement (ec);
+ else
+ source.Emit (ec);
+ }
+
+ foreach (var el in elements) {
+ el.Emit (ec);
+ }
+
+ // TODO: Needs arguments check
+ var ctor = MemberCache.FindMember (type, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly) as MethodSpec;
+
+ ec.Emit (OpCodes.Newobj, ctor);
+ }
+ }
+
+ class TupleDeconstruct : ExpressionStatement, IAssignMethod
+ {
+ Expression source;
+ List<Expression> targetExprs;
+ List<LocalVariable> variablesToInfer;
+ Expression instance;
+
+ public TupleDeconstruct (List<Expression> targetExprs, Expression source, Location loc)
+ {
+ this.source = source;
+ this.targetExprs = targetExprs;
+ this.loc = loc;
+ }
+
+ public TupleDeconstruct (List<Expression> targetExprs, List<LocalVariable> variables, Expression source, Location loc)
+ : this (targetExprs, source, loc)
+ {
+ this.variablesToInfer = variables;
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext ec)
+ {
+ ec.Report.Error (832, loc, "An expression tree cannot contain an assignment operator");
+
+ throw new NotImplementedException ();
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ var src = source.Resolve (rc);
+ if (src == null)
+ return null;
+
+ if (InternalType.HasNoType (src.Type)) {
+ rc.Report.Error (8131, source.Location, "Deconstruct assignment requires an expression with a type on the right-hand-side");
+ return null;
+ }
+
+ var src_type = src.Type;
+
+ if (src_type.IsTupleType) {
+ if (src_type.Arity != targetExprs.Count) {
+ rc.Report.Error (8132, loc, "Cannot deconstruct a tuple of `{0}' elements into `{1}' variables",
+ src_type.Arity.ToString (), targetExprs.Count.ToString ());
+ return null;
+ }
+
+ var tupleLiteral = src as TupleLiteral;
+ if (tupleLiteral == null && !ExpressionAnalyzer.IsInexpensiveLoad (src)) {
+ var expr_variable = LocalVariable.CreateCompilerGenerated (source.Type, rc.CurrentBlock, loc);
+ source = new CompilerAssign (expr_variable.CreateReferenceExpression (rc, loc), source, loc);
+ instance = expr_variable.CreateReferenceExpression (rc, loc);
+ }
+
+ for (int i = 0; i < targetExprs.Count; ++i) {
+ var tle = src_type.TypeArguments [i];
+
+ var lv = variablesToInfer? [i];
+ if (lv != null) {
+ if (InternalType.HasNoType (tle)) {
+ rc.Report.Error (8130, Location, "Cannot infer the type of implicitly-typed deconstruction variable `{0}'", lv.Name);
+ lv.Type = InternalType.ErrorType;
+ continue;
+ }
+
+ lv.Type = tle;
+ lv.PrepareAssignmentAnalysis ((BlockContext) rc);
+ }
+
+
+ var element_src = tupleLiteral == null ? new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)) : tupleLiteral.Elements [i].Expr;
+ targetExprs [i] = new SimpleAssign (targetExprs [i], element_src).Resolve (rc);
+ }
+
+ eclass = ExprClass.Value;
+ type = src.Type;
+ return this;
+ }
+
+ if (src_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
+ rc.Report.Error (8133, loc, "Cannot deconstruct dynamic objects");
+ return null;
+ }
+
+ /*
+ var args = new Arguments (targetExprs.Count);
+ foreach (var t in targetExprs) {
+ args.Add (new Argument (t, Argument.AType.Out));
+ }
+
+ var invocation = new Invocation (new MemberAccess (src, "Deconstruct"), args);
+ var res = invocation.Resolve (rc);
+ */
+
+ throw new NotImplementedException ("Custom deconstruct");
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ if (instance != null)
+ ((ExpressionStatement) source).EmitStatement (ec);
+
+ foreach (ExpressionStatement expr in targetExprs)
+ expr.EmitStatement (ec);
+ }
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
+ {
+ if (leave_copy)
+ throw new NotImplementedException ();
+
+ foreach (var lv in variablesToInfer)
+ lv.CreateBuilder (ec);
+
+ EmitStatement (ec);
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ foreach (var expr in targetExprs)
+ expr.FlowAnalysis (fc);
+ }
+
+ public void SetGeneratedFieldAssigned (FlowAnalysisContext fc)
+ {
+ if (variablesToInfer == null)
+ return;
+
+ foreach (var lv in variablesToInfer)
+ fc.SetVariableAssigned (lv.VariableInfo);
+ }
+ }
+}
\ No newline at end of file
public readonly PredefinedType FormattableString;
public readonly PredefinedType FormattableStringFactory;
+ // C# 7.0
+ public readonly PredefinedType[] Tuples;
+
public PredefinedTypes (ModuleContainer module)
{
TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
IFormattable.Define ();
FormattableString.Define ();
+
+ Tuples = new PredefinedType [8];
+ for (int i = 0; i < Tuples.Length; i++) {
+ var pt = new PredefinedType (module, MemberKind.Struct, "System", "ValueTuple", i + 1);
+ Tuples [i] = pt;
+ if (pt.Define ())
+ pt.TypeSpec.IsTupleType = true;
+ }
}
}
public readonly PredefinedMember<FieldSpec> StructLayoutCharSet;
public readonly PredefinedMember<FieldSpec> StructLayoutSize;
public readonly PredefinedMember<MethodSpec> TypeGetTypeFromHandle;
+ public readonly PredefinedMember<MethodSpec> TupleElementNamesAttributeCtor;
public PredefinedMembers (ModuleContainer module)
{
MemberFilter.Field ("Size", btypes.Int));
TypeGetTypeFromHandle = new PredefinedMember<MethodSpec> (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle);
+
+ TupleElementNamesAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.TupleElementNames,
+ MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
+ ArrayContainer.MakeType (module, btypes.String))));
}
}
}
}
+ public bool HasNamedTupleElement {
+ get {
+ return (state & StateFlags.HasNamedTupleElement) != 0;
+ }
+ }
+
//
// Returns a list of all interfaces including
// interfaces from base type or base interfaces
}
}
+ //
+ // Returns true for instances of any System.ValueTuple<......> type
+ //
+ public virtual bool IsTupleType {
+ get {
+ return (state & StateFlags.Tuple) != 0;
+ }
+ set {
+ state = value ? state | StateFlags.Tuple : state & ~StateFlags.Tuple;
+ }
+ }
+
// TODO: Should probably do
// IsGenericType -- recursive
// HasTypeParameter -- non-recursive
if (IsNested) {
s = DeclaringType.GetSignatureForError ();
} else if (MemberDefinition is AnonymousTypeClass) {
- return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
+ return ((AnonymousTypeClass)MemberDefinition).GetSignatureForError ();
+ } else if (IsTupleType) {
+ return FormatTupleSignature ();
} else {
s = MemberDefinition.Namespace;
}
return s + Name + GetTypeNameSignature ();
}
+ string FormatTupleSignature ()
+ {
+ var sb = new StringBuilder ();
+ sb.Append ("(");
+ for (int i = 0; i < TypeArguments.Length; ++i) {
+ if (i != 0)
+ sb.Append (", ");
+
+ sb.Append (TypeArguments[i].GetSignatureForError ());
+ }
+ sb.Append (")");
+
+ return sb.ToString ();
+ }
+
public string GetSignatureForErrorIncludingAssemblyName ()
{
var imported = MemberDefinition.DeclaringAssembly as ImportedAssemblyDefinition;
}
#endregion
+
+ public static bool HasNoType (TypeSpec type)
+ {
+ return type == AnonymousMethod || type == MethodGroup || type == NullLiteral || type == ThrowExpr;
+ }
}
//
{
}
-class C
+class B<T>
+{
+}
+
+class C : B<dynamic>
{
public C (dynamic d)
{
if (t.GetConstructors ()[0].GetCustomAttributes (ca, false).Length != 0)
return 21;
+ if (t.GetCustomAttributes (ca, false).Length != 1)
+ return 22;
+
// Transformations
DynamicAttribute da;
da = t.GetMember ("t")[0].GetCustomAttributes (ca, false)[0] as DynamicAttribute;
gtest-230.cs
test-pattern-02.cs
+test-pattern-04.cs
+test-pattern-05.cs
+test-pattern-07.cs
--- /dev/null
+using System;
+
+static class X
+{
+ static (int, string) Test1 ()
+ {
+ return ValueTuple.Create (1, "2");
+ }
+
+ static void Test2 ((int Item1, int Item2) arg)
+ {
+ }
+
+ static void Test3 ((int a, string b) arg)
+ {
+ }
+
+ static (int a, string b) Test4 ()
+ {
+ return ValueTuple.Create (1, "x");
+ }
+
+ static int Main ()
+ {
+ var res = Test1 ();
+ if (res.Item1 != 1) {
+ return 1;
+ }
+
+ if (res.Item2 != "2") {
+ return 2;
+ }
+
+ ValueTuple<int, string> res2 = res;
+
+ Test3 (ValueTuple.Create (1, "2"));
+
+ var res3 = Test4 ();
+ if (res3.Item1 != 1)
+ return 3;
+
+ if (res3.a != 1)
+ return 4;
+
+ if (res3.Item2 != "x")
+ return 5;
+
+ if (res3.b != "x")
+ return 6;
+
+ return 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+class TupleConversions
+{
+ public static void Main ()
+ {
+ object oarg = 4;
+ (sbyte v1, long v2) t1 = (-1, 2);
+ var t2 = (-1, 2);
+
+ IComparable o = (x1: "a", x2: 1.ToString ());
+
+ var arg = (x1: 1, x2: 1.ToString ());
+ if (arg.x2 != "1")
+ return;
+
+ Foo ((x1: (oarg, 'v'), x2: 1.ToString ()));
+
+ Test3 (ValueTuple.Create (1, "2"));
+
+ (int v1, string v2) y = (1, null);
+
+ (int v1, Action v2) y2 = (1, Main);
+ (int v1, Action v2) y3 = (ValueTuple<int, Action>) (1, Main);
+
+ (string v1, object v2) b = ("a", "b");
+
+ (int v1, long v2)? x = null;
+ }
+
+ static void Foo<T> (T arg)
+ {
+ }
+
+ static void Test3 ((long a, object b) arg)
+ {
+ }
+}
--- /dev/null
+using System;
+using System.Linq.Expressions;
+
+class TupleDeconstruct
+{
+ static int s_xx;
+ static long s_yy;
+
+ public static int Main ()
+ {
+ var (xx, yy) = (1, 2);
+ if (xx != 1)
+ return 1;
+
+ if (yy != 2)
+ return 2;
+
+ int x, y;
+ (x, y) = (1, 2);
+ if (x != 1)
+ return 3;
+
+ if (y != 2)
+ return 4;
+
+ (s_xx, s_yy) = Test3 ();
+ if (s_xx != 1)
+ return 5;
+
+ if (s_yy != 3)
+ return 6;
+
+// var cwd = new ClassWithDeconstruct ();
+// var (m1, m2) = cwd;
+
+// (string, string) ss = cwd; // Error
+
+ return 0;
+ }
+
+ static void Test2 ()
+ {
+ var c = new C ();
+ (c.Prop1, c.Prop2) = (1, 2);
+ }
+
+ static (int, long) Test3 ()
+ {
+ return (1, 3);
+ }
+
+ static void TestCustom ()
+ {
+ return;
+ }
+}
+
+class ClassWithDeconstruct
+{
+ public void Deconstruct (out string f, out string s)
+ {
+ f = "a";
+ s = "z";
+ }
+}
+
+class C
+{
+ public int Prop1 { get; set; }
+ public int Prop2 { get; set; }
+}
\ No newline at end of file
--- /dev/null
+// Compiler options: -t:library
+
+using System;
+using System.Collections.Generic;
+
+public class X
+{
+ public static (int a, string, bool b, object) Test1 ()
+ {
+ return ValueTuple.Create (1, "2", true, new X ());
+ }
+
+ public static (int x, (int x2, string y2), bool z) Field;
+}
--- /dev/null
+// Compiler options: -r:test-tuple-04-lib.dll
+
+class Test
+{
+ public static int Main ()
+ {
+ var x = X.Test1 ();
+ if (x.b != true)
+ return 1;
+
+ var z = X.Field;
+ if (z.z != false)
+ return 2;
+
+ return 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+//
+// tuple names attribute decoration
+//
+
+using System;
+using System.Collections;
+using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+using System.Linq;
+
+interface I<T>
+{
+}
+
+class B<T>
+{
+}
+
+class C // : B<(int a, int b)> // TODO: I<(a, b)
+{
+ public C((int a, int b) d)
+ {
+ }
+
+ public (int a, int b) a;
+ public (int, (int a, int b)) c;
+
+ public (int a, int b) Prop { set; get; }
+ public (int a, int b) Prop2 { set { } }
+
+ public (int a, int b)? this[(int a, int b) d] { set { } get { return null; } }
+
+ public (int a, int b)? Method(ref (int a, int b) d)
+ {
+ return null;
+ }
+
+ public (int a, int b)[] t;
+ public (int a, int b)[,] t2;
+ // TODO: public Func<(int a, int b), int, (int c, int d)[]> v;
+ // public I<(int a, int b)>[] iface;
+ // TODO: public Action<(long, (long u, long))[], object, (int a, int b)> d2;
+ public (((int aa1, int aa2) a1, (int, int) a2) x1, ((int cc1, int cc2) b1, (int dd1, int dd2) b2) x2) d3;
+}
+
+delegate (int a, int b) Del((int a, int b) d);
+
+class Test
+{
+ public static int Main()
+ {
+ Type t = typeof(C);
+ Type ca = typeof(TupleElementNamesAttribute);
+ TupleElementNamesAttribute da;
+
+ if (t.GetMember("a")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 1;
+
+ if (t.GetMember("c")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 3;
+
+ if (t.GetMember("Prop")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 4;
+
+ if (t.GetMember("get_Prop")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 5;
+
+ if (t.GetMethod("get_Prop").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+ return 6;
+
+ if (t.GetMember("set_Prop")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 7;
+
+ if (t.GetMethod("set_Prop").ReturnParameter.GetCustomAttributes(ca, false).Length != 0)
+ return 8;
+
+ if (t.GetMethod("set_Prop").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 9;
+
+ if (t.GetMember("Prop2")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 10;
+
+ if (t.GetMember("set_Prop2")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 11;
+
+ if (t.GetMember("Item")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 12;
+
+ if (t.GetMethod("get_Item").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+ return 13;
+
+ if (t.GetMethod("get_Item").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 14;
+
+ if (t.GetMethod("set_Item").ReturnParameter.GetCustomAttributes(ca, false).Length != 0)
+ return 15;
+
+ if (t.GetMethod("set_Item").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 16;
+
+ if (t.GetMethod("set_Item").GetParameters()[1].GetCustomAttributes(ca, false).Length != 1)
+ return 17;
+
+ if (t.GetMember("Method")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 18;
+
+ var res = t.GetMethod("Method").GetParameters()[0].GetCustomAttributes(ca, false);
+ if (res.Length != 1)
+ return 19;
+
+ da = res[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 190;
+ if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ return 191;
+
+ if (t.GetConstructors()[0].GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 20;
+
+ if (t.GetConstructors()[0].GetCustomAttributes(ca, false).Length != 0)
+ return 21;
+
+ // if (t.GetCustomAttributes(ca, false).Length != 1)
+ // return 22;
+
+ // Transformations
+ da = t.GetMember("t")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 40;
+
+ if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ return 41;
+
+ da = t.GetMember("t2")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 42;
+
+ if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ return 43;
+
+ //da = t.GetMember("v")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ //if (da == null)
+ // return 44;
+
+ //if (!da.TransformNames.SequenceEqual(new string[] { "a", "b", "c", "d" }))
+ // return 45;
+
+ //da = t.GetMember("iface")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ //if (da == null)
+ // return 46;
+
+ //if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ // return 47;
+
+ //da = t.GetMember("d2")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ //if (da == null)
+ // return 48;
+ //if (!da.TransformNames.SequenceEqual(new string[] { null, null, "u", null, "a", "b" }))
+ // return 49;
+
+ da = t.GetMember("d3")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 50;
+ if (!da.TransformNames.SequenceEqual(new string[] { "x1", "x2", "a1", "a2", "aa1", "aa2", null, null, "b1", "b2", "cc1", "cc2", "dd1", "dd2" }))
+ return 51;
+
+ t = typeof(Del);
+
+ if (t.GetMember("Invoke")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 100;
+
+ if (t.GetMethod("Invoke").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 101;
+
+ if (t.GetMethod("Invoke").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+ return 102;
+
+ Console.WriteLine("ok");
+ return 0;
+ }
+}
</type>
<type name="Test">
<method name="Int32 Main()" attrs="150">
- <size>1292</size>
+ <size>1316</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
<size>0</size>
</method>
</type>
+ <type name="B`1[T]">
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
</test>
<test name="dtest-002.cs">
<type name="C">
</method>
</type>
</test>
- <test name="test-pattern-04.cs">
- <type name="RecursivePattern">
- <method name="Int32 Main()" attrs="145">
- <size>750</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="C1">
- <method name="Boolean op_Is(C1, Int32 ByRef)" attrs="2198">
- <size>13</size>
- </method>
- <method name="Boolean op_Is(C1, C1 ByRef, C1 ByRef)" attrs="2198">
- <size>16</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="S">
- <method name="Boolean op_Is(S, System.Nullable`1[System.Int32] ByRef, System.Decimal ByRef)" attrs="2198">
- <size>34</size>
- </method>
- </type>
- </test>
- <test name="test-pattern-05.cs">
- <type name="RecursiveNamedPattern">
- <method name="Int32 Main()" attrs="150">
- <size>204</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="C">
- <method name="Boolean op_Is(C, Int64 ByRef, System.String ByRef)" attrs="2198">
- <size>22</size>
- </method>
- <method name="Boolean op_Is(C)" attrs="2198">
- <size>10</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- </test>
<test name="test-pattern-06.cs">
<type name="RecursiveNamedPattern">
<method name="Int32 Main()" attrs="150">
</method>
</type>
</test>
- <test name="test-pattern-07.cs">
- <type name="PropertyPattern">
- <method name="Int32 Main()" attrs="145">
- <size>684</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="X">
- <method name="System.Object get_Field()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_Field(System.Object)" attrs="2182">
- <size>8</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="Y">
- <method name="Char get_Prop()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_Prop(Char)" attrs="2182">
- <size>8</size>
- </method>
- <method name="Boolean op_Is(Y, Int32 ByRef)" attrs="2198">
- <size>13</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="X">
- <method name="System.Object get_Value()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_Value(System.Object)" attrs="2182">
- <size>8</size>
- </method>
- </type>
- <type name="<PatternMatchingHelper>">
- <method name="Boolean NumberMatcher(System.Object, System.Object, Boolean)" attrs="150">
- <size>69</size>
- </method>
- </type>
- <type name="X">
- <method name="System.Nullable`1[System.Int64] get_NullableValue()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_NullableValue(System.Nullable`1[System.Int64])" attrs="2182">
- <size>8</size>
- </method>
- </type>
- </test>
<test name="test-pragma-unrecognized.cs">
<type name="C">
<method name="Void Main()" attrs="150">
</method>
</type>
</test>
+ <test name="test-tuple-01.cs">
+ <type name="X">
+ <method name="System.ValueTuple`2[System.Int32,System.String] Test1()" attrs="145">
+ <size>20</size>
+ </method>
+ <method name="Void Test2(System.ValueTuple`2[System.Int32,System.Int32])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void Test3(System.ValueTuple`2[System.Int32,System.String])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="System.ValueTuple`2[System.Int32,System.String] Test4()" attrs="145">
+ <size>40</size>
+ </method>
+ <method name="Int32 Main()" attrs="145">
+ <size>210</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-02.cs">
+ <type name="TupleConversions">
+ <method name="Void Main()" attrs="150">
+ <size>314</size>
+ </method>
+ <method name="Void Foo[T](T)" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void Test3(System.ValueTuple`2[System.Int64,System.Object])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-03.cs">
+ <type name="TupleDeconstruct">
+ <method name="Int32 Main()" attrs="150">
+ <size>144</size>
+ </method>
+ <method name="Void Test2()" attrs="145">
+ <size>22</size>
+ </method>
+ <method name="Void TestCustom()" attrs="145">
+ <size>7</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="ClassWithDeconstruct">
+ <method name="Void Deconstruct(System.String ByRef, System.String ByRef)" attrs="134">
+ <size>16</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="C">
+ <method name="Int32 get_Prop1()" attrs="2182">
+ <size>14</size>
+ </method>
+ <method name="Void set_Prop1(Int32)" attrs="2182">
+ <size>8</size>
+ </method>
+ <method name="Int32 get_Prop2()" attrs="2182">
+ <size>14</size>
+ </method>
+ <method name="Void set_Prop2(Int32)" attrs="2182">
+ <size>8</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="TupleDeconstruct">
+ <method name="System.ValueTuple`2[System.Int32,System.Int64] Test3()" attrs="145">
+ <size>17</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-04.cs">
+ <type name="Test">
+ <method name="Int32 Main()" attrs="150">
+ <size>60</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-05.cs">
+ <type name="B`1[T]">
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="C">
+ <method name="Void set_Prop(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+ <size>28</size>
+ </method>
+ <method name="System.ValueTuple`2[System.Int32,System.Int32] get_Prop()" attrs="2182">
+ <size>34</size>
+ </method>
+ <method name="Void set_Prop2(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+ <size>2</size>
+ </method>
+ <method name="Void set_Item(System.ValueTuple`2[System.Int32,System.Int32], System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]])" attrs="2182">
+ <size>2</size>
+ </method>
+ <method name="System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]] get_Item(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+ <size>18</size>
+ </method>
+ <method name="System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]] Method(System.ValueTuple`2[System.Int32,System.Int32] ByRef)" attrs="134">
+ <size>18</size>
+ </method>
+ <method name="Void .ctor(ValueTuple`2)" attrs="6278">
+ <size>8</size>
+ </method>
+ </type>
+ <type name="Del">
+ <method name="System.ValueTuple`2[System.Int32,System.Int32] Invoke(System.ValueTuple`2[System.Int32,System.Int32])" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="System.IAsyncResult BeginInvoke(System.ValueTuple`2[System.Int32,System.Int32], System.AsyncCallback, System.Object)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="System.ValueTuple`2[System.Int32,System.Int32] EndInvoke(System.IAsyncResult)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="Void .ctor(Object, IntPtr)" attrs="6278">
+ <size>0</size>
+ </method>
+ </type>
+ <type name="Test">
+ <method name="Int32 Main()" attrs="150">
+ <size>1338</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-var-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">
build_SUBDIRS = resgen gacutil security culevel cil-stringreplacer commoncryptogenerator resx2sr linker
net_4_5_SUBDIRS = gacutil
+net_4_x_SUBDIRS = gacutil
net_4_5_PARALLEL_SUBDIRS = $(net_4_5_dirs)
+net_4_x_PARALLEL_SUBDIRS = $(net_4_5_dirs)
SUBDIRS = $(build_SUBDIRS) $(net_4_5_dirs)
PROGRAM = $(topdir)/class/lib/$(PROFILE)/mdoc.exe
PROGRAM_DEPS = $(topdir)/class/lib/$(PROFILE)/monodoc.dll
-ifdef NET
-all : copy-with-deps
-
-copy-with-deps:
- -mkdir mdoc-net
- cp $(PROGRAM) mdoc-net
- cp $(topdir)/class/lib/$(PROFILE)/Commons.Xml.Relaxng.dll mdoc-net
- cp $(topdir)/class/lib/$(PROFILE)/ICSharpCode.SharpZipLib.dll mdoc-net
- cp $(topdir)/class/lib/$(PROFILE)/Mono.Cecil.dll mdoc-net
- cp $(topdir)/class/lib/$(PROFILE)/monodoc.dll mdoc-net
-endif
-
MDOC_TEST_FILES = \
Test/CLILibraryTypes.dtd \
Test/DocTest-v1.cs \
+++ /dev/null
-../../build/common/Consts.cs
-../../class/Mono.Options/Mono.Options/Options.cs
-Mono.Documentation/assembler.cs
-Mono.Documentation/dump.cs
-Mono.Documentation/exceptions.cs
-Mono.Documentation/mdoc.cs
-Mono.Documentation/monodocer.cs
-Mono.Documentation/monodocs2html.cs
-Mono.Documentation/monodocs2slashdoc.cs
-Mono.Documentation/normalize.cs
-Mono.Documentation/validate.cs
-Mono.Documentation/webdoc.cs
-Mono.Documentation/XhtmlWriter.cs
-Mono.Rocks/ObjectRocks.cs
-Mono.Rocks/StreamRocks.cs
-
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Analyzer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/CharTokenizer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/DE/GermanAnalyzer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/DE/GermanStemFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/DE/GermanStemmer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/DE/WordlistLoader.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/LetterTokenizer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/LowerCaseFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/LowerCaseTokenizer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/PerFieldAnalyzerWrapper.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/PorterStemFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/PorterStemmer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/RU/RussianAnalyzer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/RU/RussianCharsets.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/RU/RussianLetterTokenizer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/RU/RussianLowerCaseFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/RU/RussianStemFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/RU/RussianStemmer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/SimpleAnalyzer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/CharStream.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/FastCharStream.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/ParseException.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/StandardAnalyzer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/StandardFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/StandardTokenizer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/StandardTokenizerConstants.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/StandardTokenizerTokenManager.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/Token.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Standard/TokenMgrError.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/StopAnalyzer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/StopFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Token.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/TokenFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/Tokenizer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/TokenStream.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/WhitespaceAnalyzer.cs
-../monodoc/Lucene.Net/Lucene.Net/Analysis/WhitespaceTokenizer.cs
-../monodoc/Lucene.Net/Lucene.Net/Document/DateField.cs
-../monodoc/Lucene.Net/Lucene.Net/Document/Document.cs
-../monodoc/Lucene.Net/Lucene.Net/Document/Field.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/CompoundFileReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/CompoundFileWriter.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/DocumentWriter.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/FieldInfo.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/FieldInfos.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/FieldsReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/FieldsWriter.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/FilterIndexReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/IndexReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/IndexWriter.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/MultipleTermPositions.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/MultiReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentInfo.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentInfos.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentMergeInfo.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentMergeQueue.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentMerger.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentTermDocs.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentTermEnum.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentTermPositions.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/SegmentTermVector.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/Term.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermDocs.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermEnum.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermFreqVector.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermInfo.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermInfosReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermInfosWriter.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermPositions.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermPositionVector.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermVectorsReader.cs
-../monodoc/Lucene.Net/Lucene.Net/Index/TermVectorsWriter.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/CharStream.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/FastCharStream.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/MultiFieldQueryParser.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/ParseException.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/QueryParser.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/QueryParserConstants.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/QueryParserTokenManager.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/Token.cs
-../monodoc/Lucene.Net/Lucene.Net/QueryParser/TokenMgrError.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/BooleanClause.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/BooleanQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/BooleanScorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/CachingWrapperFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/ConjunctionScorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/DateFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/DefaultSimilarity.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/ExactPhraseScorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Explanation.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FieldCache.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FieldCacheImpl.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FieldDoc.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FieldDocSortedHitQueue.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FieldSortedHitQueue.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Filter.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FilteredQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FilteredTermEnum.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FuzzyQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/FuzzyTermEnum.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/HitCollector.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/HitQueue.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Hits.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/IndexSearcher.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/MultiSearcher.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/MultiTermQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/ParallelMultiSearcher.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/PhrasePositions.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/PhrasePrefixQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/PhraseQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/PhraseQueue.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/PhraseScorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/PrefixQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Query.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/QueryFilter.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/QueryTermVector.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/RangeQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/ScoreDoc.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/ScoreDocComparator.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Scorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Searchable.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Searcher.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Similarity.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/SloppyPhraseScorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Sort.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/SortComparator.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/SortComparatorSource.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/SortField.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/NearSpans.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanFirstQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanNearQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanNotQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanOrQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/Spans.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanScorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanTermQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Spans/SpanWeight.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/TermQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/TermScorer.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/TopDocs.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/TopFieldDocs.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/Weight.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/WildcardQuery.cs
-../monodoc/Lucene.Net/Lucene.Net/Search/WildcardTermEnum.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/Directory.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/FSDirectory.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/InputStream.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/Lock.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/OutputStream.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/RAMDirectory.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/RAMFile.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/RAMInputStream.cs
-../monodoc/Lucene.Net/Lucene.Net/Store/RAMOutputStream.cs
-../monodoc/Lucene.Net/Lucene.Net/SupportClass.cs
-../monodoc/Lucene.Net/Lucene.Net/Util/BitVector.cs
-../monodoc/Lucene.Net/Lucene.Net/Util/Constants.cs
-../monodoc/Lucene.Net/Lucene.Net/Util/PriorityQueue.cs
-../monodoc/Lucene.Net/Lucene.Net/Util/StringHelper.cs
-../monodoc/Mono.Documentation/ManifestResourceResolver.cs
-../monodoc/Mono.Documentation/XmlDocUtils.cs
-../monodoc/Mono.Utilities/colorizer.cs
-../monodoc/Monodoc/addins-provider.cs
-../monodoc/Monodoc/commentservice.cs
-../monodoc/Monodoc/ecma-provider.cs
-../monodoc/Monodoc/ecma2wiki.cs
-../monodoc/Monodoc/ecmaspec-provider.cs
-../monodoc/Monodoc/editing.cs
-../monodoc/Monodoc/error-provider.cs
-../monodoc/Monodoc/html-helper.cs
-../monodoc/Monodoc/index.cs
-../monodoc/Monodoc/man-provider.cs
-../monodoc/Monodoc/monohb-provider.cs
-../monodoc/Monodoc/provider.cs
-../monodoc/Monodoc/SearchableDocument.cs
-../monodoc/Monodoc/SearchableIndex.cs
-../monodoc/Monodoc/settings.cs
-../monodoc/Monodoc/simple-provider.cs
-../monodoc/Monodoc/wiki2ecma.cs
-../monodoc/Monodoc/xhtml-provider.cs
-../monodoc/Monodoc/XmlNodeWriter.cs
-
-../../build/common/Locale.cs
-../../class/System.XML/Mono.Xml.Schema/XmlSchemaValidatingReader.cs
-../../class/System.XML/Mono.Xml.Schema/XsdIdentityPath.cs
-../../class/System.XML/Mono.Xml.Schema/XsdIdentityState.cs
-../../class/System.XML/Mono.Xml.Schema/XsdKeyTable.cs
-../../class/System.XML/Mono.Xml.Schema/XsdParticleValidationState.cs
-../../class/System.XML/Mono.Xml.Schema/XsdValidatingReader.cs
-../../class/System.XML/Mono.Xml.Schema/XsdWildcard.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathDocument.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathNavigator.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathNode.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathDocument2.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter2.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathNavigator2.cs
-../../class/System.XML/Mono.Xml.XPath/DTMXPathNode2.cs
-../../class/System.XML/Mono.Xml.XPath/IdPattern.cs
-../../class/System.XML/Mono.Xml.XPath/KeyPattern.cs
-../../class/System.XML/Mono.Xml.XPath/LocationPathPattern.cs
-../../class/System.XML/Mono.Xml.XPath/Pattern.cs
-../../class/System.XML/Mono.Xml.XPath/UnionPattern.cs
-../../class/System.XML/Mono.Xml.XPath/XPathEditableDocument.cs
-../../class/System.XML/Mono.Xml.XPath/XPathNavigatorReader.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslApplyImports.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslApplyTemplates.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslAttribute.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslAvt.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslCallTemplate.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslChoose.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslComment.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslCompiledElement.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslCopy.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslCopyOf.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslElement.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslFallback.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslForEach.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslIf.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslLiteralElement.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslMessage.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslNotSupportedOperation.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslNumber.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslOperation.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslProcessingInstruction.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslTemplateContent.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslText.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslValueOf.cs
-../../class/System.XML/Mono.Xml.Xsl.Operations/XslVariable.cs
-../../class/System.XML/Mono.Xml.Xsl/Attribute.cs
-../../class/System.XML/Mono.Xml.Xsl/Compiler.cs
-../../class/System.XML/Mono.Xml.Xsl/Debug.cs
-../../class/System.XML/Mono.Xml.Xsl/Emitter.cs
-../../class/System.XML/Mono.Xml.Xsl/GenericOutputter.cs
-../../class/System.XML/Mono.Xml.Xsl/HtmlEmitter.cs
-../../class/System.XML/Mono.Xml.Xsl/MSXslScriptManager.cs
-../../class/System.XML/Mono.Xml.Xsl/Outputter.cs
-../../class/System.XML/Mono.Xml.Xsl/ScriptCompilerInfo.cs
-../../class/System.XML/Mono.Xml.Xsl/TextEmitter.cs
-../../class/System.XML/Mono.Xml.Xsl/TextOutputter.cs
-../../class/System.XML/Mono.Xml.Xsl/XmlWriterEmitter.cs
-../../class/System.XML/Mono.Xml.Xsl/XslAttributeSet.cs
-../../class/System.XML/Mono.Xml.Xsl/XslDecimalFormat.cs
-../../class/System.XML/Mono.Xml.Xsl/XslKey.cs
-../../class/System.XML/Mono.Xml.Xsl/XslOutput.cs
-../../class/System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs
-../../class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs
-../../class/System.XML/Mono.Xml.Xsl/XslTemplate.cs
-../../class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs
-../../class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs
-../../class/System.XML/Mono.Xml.Xsl/XsltDebuggerWrapper.cs
-../../class/System.XML/Mono.Xml.Xsl/XslFunctions.cs
-../../class/System.XML/Mono.Xml/IHasXmlParserContext.cs
-../../class/System.XML/Mono.Xml/IHasXmlSchemaInfo.cs
-../../class/System.XML/Mono.Xml/SubtreeXmlReader.cs
-../../class/System.XML/Mono.Xml/XmlFilterReader.cs
-../../class/System.XML/Mono.Xml/XmlNodeWriter.cs
-../../class/System.XML/System.Xml/ConformanceLevel.cs
-../../class/System.XML/System.Xml/DTDAutomata.cs
-../../class/System.XML/System.Xml/DTDObjectModel.cs
-../../class/System.XML/System.Xml/DTDReader.cs
-../../class/System.XML/System.Xml/DTDValidatingReader2.cs
-../../class/System.XML/System.Xml/EntityResolvingXmlReader.cs
-../../class/System.XML/System.Xml/EntityHandling.cs
-../../class/System.XML/System.Xml/Formatting.cs
-../../class/System.XML/System.Xml/IHasXmlNode.cs
-../../class/System.XML/System.Xml/IXmlLineInfo.cs
-../../class/System.XML/System.Xml/IHasXmlChildNode.cs
-../../class/System.XML/System.Xml/IXmlNamespaceResolver.cs
-../../class/System.XML/System.Xml/MonoFIXAttribute.cs
-../../class/System.XML/System.Xml/NameTable.cs
-../../class/System.XML/System.Xml/NewLineHandling.cs
-../../class/System.XML/System.Xml/ReadState.cs
-../../class/System.XML/../../build/common/MonoTODOAttribute.cs
-../../class/System.XML/System.Xml/ValidationType.cs
-../../class/System.XML/System.Xml/WhitespaceHandling.cs
-../../class/System.XML/System.Xml/WriteState.cs
-../../class/System.XML/System.Xml/XmlEntity.cs
-../../class/System.XML/System.Xml/XmlAttribute.cs
-../../class/System.XML/System.Xml/XmlAttributeCollection.cs
-../../class/System.XML/System.Xml/XmlCDataSection.cs
-../../class/System.XML/System.Xml/XmlConstructs.cs
-../../class/System.XML/System.Xml/XmlChar.cs
-../../class/System.XML/System.Xml/XmlCharacterData.cs
-../../class/System.XML/System.Xml/XmlComment.cs
-../../class/System.XML/System.Xml/XmlNotation.cs
-../../class/System.XML/System.Xml/XmlDeclaration.cs
-../../class/System.XML/System.Xml/XmlDocument.cs
-../../class/System.XML/System.Xml/XmlDocumentFragment.cs
-../../class/System.XML/System.Xml/XmlDocumentNavigator.cs
-../../class/System.XML/System.Xml/XmlDocumentType.cs
-../../class/System.XML/System.Xml/XmlElement.cs
-../../class/System.XML/System.Xml/XmlEntityReference.cs
-../../class/System.XML/System.Xml/XmlException.cs
-../../class/System.XML/System.Xml/XmlImplementation.cs
-../../class/System.XML/System.Xml/XmlConvert.cs
-../../class/System.XML/System.Xml/XmlDateTimeSerializationMode.cs
-../../class/System.XML/System.Xml/XmlLinkedNode.cs
-../../class/System.XML/System.Xml/XmlNameEntry.cs
-../../class/System.XML/System.Xml/XmlNameEntryCache.cs
-../../class/System.XML/System.Xml/XmlNameTable.cs
-../../class/System.XML/System.Xml/XmlNamedNodeMap.cs
-../../class/System.XML/System.Xml/XmlNamespaceScope.cs
-../../class/System.XML/System.Xml/XmlNamespaceManager.cs
-../../class/System.XML/System.Xml/XmlNode.cs
-../../class/System.XML/System.Xml/XmlNodeChangedAction.cs
-../../class/System.XML/System.Xml/XmlNodeChangedEventArgs.cs
-../../class/System.XML/System.Xml/XmlNodeChangedEventHandler.cs
-../../class/System.XML/System.Xml/XmlNodeList.cs
-../../class/System.XML/System.Xml/XmlNodeListChildren.cs
-../../class/System.XML/System.Xml/XmlNodeArrayList.cs
-../../class/System.XML/System.Xml/XmlIteratorNodeList.cs
-../../class/System.XML/System.Xml/XmlNodeOrder.cs
-../../class/System.XML/System.Xml/XmlNodeReader2.cs
-../../class/System.XML/System.Xml/XmlNodeReaderImpl.cs
-../../class/System.XML/System.Xml/XmlNodeType.cs
-../../class/System.XML/System.Xml/XmlOutputMethod.cs
-../../class/System.XML/System.Xml/XmlParserContext.cs
-../../class/System.XML/System.Xml/XmlProcessingInstruction.cs
-../../class/System.XML/System.Xml/XmlQualifiedName.cs
-../../class/System.XML/System.Xml/XmlReader.cs
-../../class/System.XML/System.Xml/XmlReaderBinarySupport.cs
-../../class/System.XML/System.Xml/XmlReaderSettings.cs
-../../class/System.XML/System.Xml/XmlResolver.cs
-../../class/System.XML/System.Xml/XmlSecureResolver.cs
-../../class/System.XML/System.Xml/XmlSignificantWhitespace.cs
-../../class/System.XML/System.Xml/XmlSpace.cs
-../../class/System.XML/System.Xml/XmlText.cs
-../../class/System.XML/System.Xml/XmlTextReader.cs
-../../class/System.XML/System.Xml/XmlTextReader2.cs
-../../class/System.XML/System.Xml/XmlTokenizedType.cs
-../../class/System.XML/System.Xml/XmlUrlResolver.cs
-../../class/System.XML/System.Xml/XmlValidatingReader.cs
-../../class/System.XML/System.Xml/XmlWhitespace.cs
-../../class/System.XML/System.Xml/XmlWriter.cs
-../../class/System.XML/System.Xml/XmlWriterSettings.cs
-../../class/System.XML/System.Xml/XmlTextWriter2.cs
-../../class/System.XML/System.Xml/XmlInputStream.cs
-../../class/System.XML/System.Xml/XmlParserInput.cs
-../../class/System.XML/System.Xml.XPath/IXPathNavigable.cs
-../../class/System.XML/System.Xml.XPath/XPathNavigator.cs
-../../class/System.XML/System.Xml.XPath/XPathExpression.cs
-../../class/System.XML/System.Xml.XPath/XPathItem.cs
-../../class/System.XML/System.Xml.XPath/XPathNamespaceScope.cs
-../../class/System.XML/System.Xml.XPath/XPathNodeIterator.cs
-../../class/System.XML/System.Xml.XPath/XPathResultType.cs
-../../class/System.XML/System.Xml.XPath/XPathNodeType.cs
-../../class/System.XML/System.Xml.XPath/XmlDataType.cs
-../../class/System.XML/System.Xml.XPath/XmlSortOrder.cs
-../../class/System.XML/System.Xml.XPath/XmlCaseOrder.cs
-../../class/System.XML/System.Xml.XPath/XPathDocument.cs
-../../class/System.XML/System.Xml.XPath/XPathException.cs
-../../class/System.XML/System.Xml.XPath/XPathComparer.cs
-../../class/System.XML/System.Xml.XPath/DefaultContext.cs
-../../class/System.XML/System.Xml.XPath/Expression.cs
-../../class/System.XML/System.Xml.XPath/Iterator.cs
-../../class/System.XML/System.Xml.XPath/Tokenizer.cs
-../../class/System.XML/System.Xml.Xsl/IXsltContextFunction.cs
-../../class/System.XML/System.Xml.Xsl/IXsltContextVariable.cs
-../../class/System.XML/System.Xml.Xsl/XslCompiledTransform.cs
-../../class/System.XML/System.Xml.Xsl/XslTransform.cs
-../../class/System.XML/System.Xml.Xsl/XsltArgumentList.cs
-../../class/System.XML/System.Xml.Xsl/XsltCompileException.cs
-../../class/System.XML/System.Xml.Xsl/XsltContext.cs
-../../class/System.XML/System.Xml.Xsl/XsltException.cs
-../../class/System.XML/System.Xml.Xsl/XsltMessageEncounteredEventArgs.cs
-../../class/System.XML/System.Xml.Xsl/XsltMessageEncounteredEventHandler.cs
-../../class/System.XML/System.Xml.Xsl/XsltSettings.cs
-../../class/System.XML/System.Xml.Schema/BuiltInDatatype.cs
-../../class/System.XML/System.Xml.Schema/IXmlSchemaInfo.cs
-../../class/System.XML/System.Xml.Schema/SchemaDataValueType.cs
-../../class/System.XML/System.Xml.Schema/ValidationEventArgs.cs
-../../class/System.XML/System.Xml.Schema/XmlAtomicValue.cs
-../../class/System.XML/System.Xml.Schema/XmlSchema.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAll.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAnnotated.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAnnotation.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAny.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAnyAttribute.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAppInfo.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAttribute.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAttributeGroup.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaAttributeGroupRef.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaChoice.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaCollection.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaCollectionEnumerator.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaCompilationSettings.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaComplexContent.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaComplexContentExtension.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaComplexContentRestriction.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaComplexType.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaContent.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaContentModel.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaContentProcessing.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaContentType.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaDatatype.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaDatatypeVariety.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaDerivationMethod.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaDocumentation.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaElement.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaEnumerationFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaException.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaExternal.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaForm.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaFractionDigitsFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaGroup.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaGroupBase.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaGroupRef.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaIdentityConstraint.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaImport.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaInclude.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaInference.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaInferenceException.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaInfo.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaKey.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaKeyref.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaLengthFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaMaxExclusiveFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaMaxInclusiveFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaMaxLengthFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaMinExclusiveFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaMinInclusiveFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaMinLengthFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaNotation.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaNumericFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaObject.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaObjectCollection.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaObjectEnumerator.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaObjectTable.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaParticle.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaPatternFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaRedefine.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSequence.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSerializer.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContent.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContentExtension.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContentRestriction.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleType.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeContent.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeList.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeRestriction.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeUnion.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaTotalDigitsFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaType.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaUnique.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaUse.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaValidator.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaValidity.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaValidationException.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaWhiteSpaceFacet.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaXPath.cs
-../../class/System.XML/System.Xml.Schema/XmlSeverityType.cs
-../../class/System.XML/System.Xml.Schema/ValidationHandler.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaUtil.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaReader.cs
-../../class/System.XML/System.Xml.Schema/XmlSchemaValidationFlags.cs
-../../class/System.XML/System.Xml.Schema/XmlTypeCode.cs
-../../class/System.XML/System.Xml.Schema/XmlValueGetter.cs
-../../class/System.XML/System.Xml.Serialization/IXmlTextParser.cs
-../../class/System.XML/System.Xml.Serialization/CodeExporter.cs
-../../class/System.XML/System.Xml.Serialization/CodeGenerationOptions.cs
-../../class/System.XML/System.Xml.Serialization/CodeIdentifier.cs
-../../class/System.XML/System.Xml.Serialization/CodeIdentifiers.cs
-../../class/System.XML/System.Xml.Serialization/IXmlSerializable.cs
-../../class/System.XML/System.Xml.Serialization/ImportContext.cs
-../../class/System.XML/System.Xml.Serialization/KeyHelper.cs
-../../class/System.XML/System.Xml.Serialization/MapCodeGenerator.cs
-../../class/System.XML/System.Xml.Serialization/ReflectionHelper.cs
-../../class/System.XML/System.Xml.Serialization/SchemaImporter.cs
-../../class/System.XML/System.Xml.Serialization/SchemaTypes.cs
-../../class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs
-../../class/System.XML/System.Xml.Serialization/SerializationCodeGeneratorConfiguration.cs
-../../class/System.XML/System.Xml.Serialization/SerializationSource.cs
-../../class/System.XML/System.Xml.Serialization/SoapAttributeAttribute.cs
-../../class/System.XML/System.Xml.Serialization/SoapAttributeOverrides.cs
-../../class/System.XML/System.Xml.Serialization/SoapAttributes.cs
-../../class/System.XML/System.Xml.Serialization/SoapCodeExporter.cs
-../../class/System.XML/System.Xml.Serialization/SoapElementAttribute.cs
-../../class/System.XML/System.Xml.Serialization/SoapEnumAttribute.cs
-../../class/System.XML/System.Xml.Serialization/SoapIgnoreAttribute.cs
-../../class/System.XML/System.Xml.Serialization/SoapIncludeAttribute.cs
-../../class/System.XML/System.Xml.Serialization/SoapSchemaImporter.cs
-../../class/System.XML/System.Xml.Serialization/SoapSchemaExporter.cs
-../../class/System.XML/System.Xml.Serialization/SoapSchemaMember.cs
-../../class/System.XML/System.Xml.Serialization/SoapReflectionImporter.cs
-../../class/System.XML/System.Xml.Serialization/SoapTypeAttribute.cs
-../../class/System.XML/System.Xml.Serialization/TypeData.cs
-../../class/System.XML/System.Xml.Serialization/TypeMember.cs
-../../class/System.XML/System.Xml.Serialization/TypeTranslator.cs
-../../class/System.XML/System.Xml.Serialization/UnreferencedObjectEventArgs.cs
-../../class/System.XML/System.Xml.Serialization/UnreferencedObjectEventHandler.cs
-../../class/System.XML/System.Xml.Serialization/XmlAnyAttributeAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlAnyElementAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlAnyElementAttributes.cs
-../../class/System.XML/System.Xml.Serialization/XmlArrayAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlArrayItemAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlArrayItemAttributes.cs
-../../class/System.XML/System.Xml.Serialization/XmlAttributeAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlAttributeEventArgs.cs
-../../class/System.XML/System.Xml.Serialization/XmlAttributeEventHandler.cs
-../../class/System.XML/System.Xml.Serialization/XmlAttributeOverrides.cs
-../../class/System.XML/System.Xml.Serialization/XmlAttributes.cs
-../../class/System.XML/System.Xml.Serialization/XmlCodeExporter.cs
-../../class/System.XML/System.Xml.Serialization/XmlChoiceIdentifierAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs
-../../class/System.XML/System.Xml.Serialization/XmlDeserializationEvents.cs
-../../class/System.XML/System.Xml.Serialization/XmlElementAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlElementAttributes.cs
-../../class/System.XML/System.Xml.Serialization/XmlElementEventArgs.cs
-../../class/System.XML/System.Xml.Serialization/XmlEnumAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlIgnoreAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlIncludeAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlMemberMapping.cs
-../../class/System.XML/System.Xml.Serialization/XmlMembersMapping.cs
-../../class/System.XML/System.Xml.Serialization/XmlMapping.cs
-../../class/System.XML/System.Xml.Serialization/XmlMappingAccess.cs
-../../class/System.XML/System.Xml.Serialization/XmlNamespaceDeclarationsAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlNodeEventArgs.cs
-../../class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs
-../../class/System.XML/System.Xml.Serialization/XmlReflectionMember.cs
-../../class/System.XML/System.Xml.Serialization/XmlRootAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlSchemaEnumerator.cs
-../../class/System.XML/System.Xml.Serialization/XmlSchemaExporter.cs
-../../class/System.XML/System.Xml.Serialization/XmlSchemaImporter.cs
-../../class/System.XML/System.Xml.Serialization/XmlSchemaProviderAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlSchemas.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationCollectionFixupCallback.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationFixupCallback.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationGeneratedCode.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationReadCallback.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationWriteCallback.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationWriter.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializer.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializerAssemblyAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializerFactory.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializerImplementation.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializerNamespaces.cs
-../../class/System.XML/System.Xml.Serialization/XmlSerializerVersionAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlTextAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlTypeAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlTypeMapElementInfo.cs
-../../class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs
-../../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberAttribute.cs
-../../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberElement.cs
-../../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberNamespaces.cs
-../../class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs
-../../class/System.XML/System.Xml.Serialization/XmlElementEventHandler.cs
-../../class/System.XML/System.Xml.Serialization/XmlNodeEventHandler.cs
-../../class/System.XML/System.Xml.Serialization.Advanced/SchemaImporterExtension.cs
-../../class/System.XML/System.Xml.Serialization.Advanced/SchemaImporterExtensionCollection.cs
-../../class/System.XML/System.Xml.Serialization.Configuration/DateTimeSerializationSection.cs
-../../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionElement.cs
-../../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionElementCollection.cs
-../../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionsSection.cs
-../../class/System.XML/System.Xml.Serialization.Configuration/SerializationSectionGroup.cs
-../../class/System.XML/System.Xml.Serialization.Configuration/XmlSerializerSection.cs
-../../class/System.XML/System.Xml/XQueryConvert.cs
-../../class/System.XML/System.Xml.XPath/Parser.cs
-../../class/System.XML/Mono.Xml.Xsl/PatternParser.cs
-../../class/System.XML/Mono.Xml.Xsl/PatternTokenizer.cs
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{7DA7CD97-614F-4BCD-A2FA-B379590CEA48}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <RootNamespace>mdoc</RootNamespace>
- <AssemblyName>mdoc</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
- <DebugSymbols>True</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>False</Optimize>
- <OutputPath>bin\Debug</OutputPath>
- <DefineConstants>DEBUG;NET_4_5</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <PlatformTarget>x86</PlatformTarget>
- <Externalconsole>True</Externalconsole>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
- <DebugType>none</DebugType>
- <Optimize>False</Optimize>
- <OutputPath>bin\Release</OutputPath>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <PlatformTarget>x86</PlatformTarget>
- <Externalconsole>True</Externalconsole>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Web" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="ICSharpCode.SharpZipLib" />
- <Reference Include="System.Xml" />
- <Reference Include="monodoc">
- <HintPath>..\..\class\lib\net_4_x\monodoc.dll</HintPath>
- </Reference>
- <Reference Include="Mono.Cecil">
- <HintPath>..\..\class\lib\net_4_x\Mono.Cecil.dll</HintPath>
- </Reference>
- </ItemGroup>
- <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
- <ItemGroup>
- <Compile Include="..\..\build\common\Consts.cs">
- <Link>Build\Common\Consts.cs</Link>
- </Compile>
- <Compile Include="..\..\class\Mono.Options\Mono.Options\Options.cs">
- <Link>Mono.Options\Options.cs</Link>
- </Compile>
- <Compile Include="Mono.Rocks\ObjectRocks.cs" />
- <Compile Include="Mono.Rocks\StreamRocks.cs" />
- <Compile Include="Mono.Documentation\assembler.cs" />
- <Compile Include="Mono.Documentation\dump.cs" />
- <Compile Include="Mono.Documentation\ecmadoc.cs" />
- <Compile Include="Mono.Documentation\mdoc.cs" />
- <Compile Include="Mono.Documentation\MdocFile.cs" />
- <Compile Include="Mono.Documentation\monodocer.cs" />
- <Compile Include="Mono.Documentation\monodocs2html.cs" />
- <Compile Include="Mono.Documentation\monodocs2slashdoc.cs" />
- <Compile Include="Mono.Documentation\msitomsx.cs" />
- <Compile Include="Mono.Documentation\normalize.cs" />
- <Compile Include="Mono.Documentation\validate.cs" />
- <Compile Include="Mono.Documentation\webdoc.cs" />
- <Compile Include="Mono.Documentation\XhtmlWriter.cs" />
- <Compile Include="Mono.Documentation\exceptions.cs" />
- <Compile Include="Mono.Documentation\index.cs" />
- <Compile Include="Mono.Documentation\preserver.cs" />
- </ItemGroup>
- <ItemGroup>
- <EmbeddedResource Include="Resources\defaulttemplate.xsl">
- <LogicalName>defaulttemplate.xsl</LogicalName>
- </EmbeddedResource>
- <EmbeddedResource Include="Resources\monodoc-ecma.xsd">
- <LogicalName>monodoc-ecma.xsd</LogicalName>
- </EmbeddedResource>
- <EmbeddedResource Include="Resources\msitomsx.xsl">
- <LogicalName>msitomsx.xsl</LogicalName>
- </EmbeddedResource>
- <EmbeddedResource Include="Resources\overview.xsl">
- <LogicalName>overview.xsl</LogicalName>
- </EmbeddedResource>
- <EmbeddedResource Include="Resources\stylesheet.xsl">
- <LogicalName>stylesheet.xsl</LogicalName>
- </EmbeddedResource>
- </ItemGroup>
- <ItemGroup>
- <None Include="..\..\class\monodoc\Resources\mdoc-html-format.xsl">
- <Link>Resources\mdoc-html-format.xsl</Link>
- </None>
- <None Include="..\..\class\monodoc\Resources\mdoc-html-utils.xsl">
- <Link>Resources\mdoc-html-utils.xsl</Link>
- </None>
- <None Include="..\..\class\monodoc\Resources\mdoc-sections-css.xsl">
- <Link>Resources\mdoc-sections-css.xsl</Link>
- </None>
- <None Include="..\..\class\monodoc\Resources\mono-ecma-css.xsl">
- <Link>Resources\mono-ecma-css.xsl</Link>
- </None>
- </ItemGroup>
-</Project>
\ No newline at end of file
+++ /dev/null
-\r
-Microsoft Visual Studio Solution File, Format Version 11.00\r
-# Visual Studio 2010\r
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mdoc", "mdoc.csproj", "{7DA7CD97-614F-4BCD-A2FA-B379590CEA48}"\r
-EndProject\r
-Global\r
- GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
- Debug|x86 = Debug|x86\r
- Release|x86 = Release|x86\r
- EndGlobalSection\r
- GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
- {7DA7CD97-614F-4BCD-A2FA-B379590CEA48}.Debug|x86.ActiveCfg = Debug|x86\r
- {7DA7CD97-614F-4BCD-A2FA-B379590CEA48}.Debug|x86.Build.0 = Debug|x86\r
- {7DA7CD97-614F-4BCD-A2FA-B379590CEA48}.Release|x86.ActiveCfg = Release|x86\r
- {7DA7CD97-614F-4BCD-A2FA-B379590CEA48}.Release|x86.Build.0 = Release|x86\r
- EndGlobalSection\r
- GlobalSection(MonoDevelopProperties) = preSolution\r
- StartupItem = mdoc.csproj\r
- EndGlobalSection\r
-EndGlobal\r
ASN1_GENERALIZEDTIME *gtime;
struct tm tm;
int64_t epoch;
+ int ret;
memset (&tm, 0, sizeof (tm));
gtime = ASN1_TIME_to_generalizedtime (time, NULL);
- /* FIXME: check return value of asn1_generalizedtime_to_tm () */
- asn1_generalizedtime_to_tm (&tm, gtime);
+ ret = asn1_generalizedtime_to_tm (&tm, gtime);
ASN1_GENERALIZEDTIME_free (gtime);
+
+ /* FIXME: check the return value in managed code */
+ if (ret == 0) {
+ return 0;
+ }
+
epoch = btls_timegm64 (&tm);
return epoch;
+++ /dev/null
-#!/bin/sh
-
-DIR=$1; shift
-FILELIST=$1; shift
-LOFILELIST=$1 ; shift
-TARGET=$1; shift
-STATIC=$1; shift
-AR=$1; shift
-RANLIB=$1; shift
-
-HEADER="# Generated by Martin's tool $0, not libtool"
-
-test -f $TARGET && exit 0
-
-rm -f $FILELIST
-rm -f $LOFILELIST
-
-while [ "$1" != "--" ]; do
- file=$1; shift
- filename=`basename $file`
- LOFILE=$file.lo
- echo "$HEADER" > $LOFILE
- if [ "$STATIC" = "static" ]; then
- echo "non_pic_object='$filename'" >> $LOFILE
- else
- echo "pic_object='$filename'" >> $LOFILE
- fi
- echo "$DIR/$file " >> $FILELIST
- echo "$DIR/$LOFILE " >> $LOFILELIST
-done
-
-(cd $DIR && $AR cr $TARGET `cat $FILELIST` && $RANLIB $TARGET)
-
<opcode name="mono_atomic_store_i4" input="PopI+PopI" output="Push0" args="InlineI" o1="0xF0" o2="0x1A" flow="next" />
<opcode name="mono_get_last_error" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1B" flow="next" />
<opcode name="mono_get_rgctx_arg" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1C" flow="next" />
+<opcode name="mono_ldptr_profiler_allocation_count" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1D" flow="next" />
</opdesc>
OPDEF(CEE_MONO_ATOMIC_STORE_I4, "mono_atomic_store_i4", PopI+PopI, Push0, InlineI, X, 2, 0xF0, 0x1A, NEXT)
OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1B, NEXT)
OPDEF(CEE_MONO_GET_RGCTX_ARG, "mono_get_rgctx_arg", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1C, NEXT)
+OPDEF(CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT, "mono_ldptr_profiler_allocation_count", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1D, NEXT)
#ifndef OPALIAS
#define _MONO_CIL_OPALIAS_DEFINED_
#define OPALIAS(a,s,r)
w32process.h \
w32process-internals.h \
profiler.c \
+ profiler-events.h \
profiler-private.h \
rand.h \
rand.c \
data->domain = MONO_HANDLE_RAW (ad);
data->friendly_name = g_strdup (friendly_name);
- mono_profiler_appdomain_name (data, data->friendly_name);
+ MONO_PROFILER_RAISE (domain_name, (data, data->friendly_name));
MonoStringHandle app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base);
if (MONO_HANDLE_IS_NULL (app_base)) {
params [2] = &isrefonly;
MonoReflectionAssemblyHandle result = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_runtime_invoke_checked (method, domain->domain, params, error));
ret = !MONO_HANDLE_IS_NULL (result) ? MONO_HANDLE_GETVAL (result, assembly) : NULL;
+
+ if (ret && !refonly && ret->ref_only) {
+ /* .NET Framework throws System.IO.FileNotFoundException in this case */
+ mono_error_set_file_not_found (error, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only");
+ ret = NULL;
+ goto leave;
+ }
leave:
HANDLE_FUNCTION_RETURN_VAL (ret);
}
gboolean
mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
{
+ g_assert (assembly && assembly->image);
+ /* .NET Framework appears to ignore the attribute on dynamic
+ * assemblies, so don't call this function for dynamic assemblies. */
+ g_assert (!image_is_dynamic (assembly->image));
error_init (error);
/*
ass->ref_only = refonly;
ass->image = image;
- mono_profiler_assembly_event (ass, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (assembly_loading, (ass));
mono_assembly_fill_assembly_name (image, &ass->aname);
mono_assembly_invoke_load_hook (ass);
- mono_profiler_assembly_loaded (ass, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (assembly_loaded, (ass));
return ass;
}
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;
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;
{
MonoError refasm_error;
error_init (&refasm_error);
- if (candidate && !refonly && mono_assembly_has_reference_assembly_attribute (candidate, &refasm_error)) {
- candidate = NULL;
+ if (candidate && !refonly) {
+ /* .NET Framework seems to not check for ReferenceAssemblyAttribute on dynamic assemblies */
+ if (!image_is_dynamic (candidate->image) &&
+ mono_assembly_has_reference_assembly_attribute (candidate, &refasm_error))
+ candidate = NULL;
}
mono_error_cleanup (&refasm_error);
return candidate;
if (InterlockedDecrement (&assembly->ref_count) > 0)
return FALSE;
- mono_profiler_assembly_event (assembly, MONO_PROFILE_START_UNLOAD);
+ MONO_PROFILER_RAISE (assembly_unloading, (assembly));
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading assembly %s [%p].", assembly->aname.name, assembly);
g_slist_free (assembly->friend_assembly_names);
g_free (assembly->basedir);
- mono_profiler_assembly_event (assembly, MONO_PROFILE_END_UNLOAD);
+ MONO_PROFILER_RAISE (assembly_unloaded, (assembly));
return TRUE;
}
static gboolean gc_initialized = FALSE;
static mono_mutex_t mono_gc_lock;
+typedef void (*GC_push_other_roots_proc)(void);
+
+static GC_push_other_roots_proc default_push_other_roots;
+static GHashTable *roots;
+
+static void
+mono_push_other_roots(void);
+
static void
register_test_toggleref_callback (void);
}
#endif
+ roots = g_hash_table_new (NULL, NULL);
+ default_push_other_roots = GC_push_other_roots;
+ GC_push_other_roots = mono_push_other_roots;
+
#if !defined(PLATFORM_ANDROID)
/* If GC_no_dls is set to true, GC_find_limit is not called. This causes a seg fault on Android. */
GC_no_dls = TRUE;
static void
on_gc_notification (GC_EventType event)
{
- MonoGCEvent e = (MonoGCEvent)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)
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.
break;
}
- mono_profiler_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_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0);
+ 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_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0));
break;
default:
break;
mono_perfcounters->gc_gen0size = heap_size;
}
#endif
- mono_profiler_gc_heap_resize (new_size);
+
+ MONO_PROFILER_RAISE (gc_resize, (new_size));
+}
+
+typedef struct {
+ char *start;
+ char *end;
+} RootData;
+
+static gpointer
+register_root (gpointer arg)
+{
+ RootData* root_data = arg;
+ g_hash_table_insert (roots, root_data->start, root_data->end);
+ return NULL;
}
int
mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource source, const char *msg)
{
- /* for some strange reason, they want one extra byte on the end */
- GC_add_roots (start, start + size + 1);
+ RootData root_data;
+ root_data.start = start;
+ /* Boehm root processing requires one byte past end of region to be scanned */
+ root_data.end = start + size + 1;
+ GC_call_with_alloc_lock (register_root, &root_data);
return TRUE;
}
return mono_gc_register_root (start, size, descr, source, msg);
}
+static gpointer
+deregister_root (gpointer arg)
+{
+ gboolean removed = g_hash_table_remove (roots, arg);
+ g_assert (removed);
+ return NULL;
+}
+
void
mono_gc_deregister_root (char* addr)
{
-#ifndef HOST_WIN32
- /* FIXME: libgc doesn't define this work win32 for some reason */
- /* FIXME: No size info */
- GC_remove_roots (addr, addr + sizeof (gpointer) + 1);
-#endif
+ GC_call_with_alloc_lock (deregister_root, addr);
+}
+
+static void
+push_root (gpointer key, gpointer value, gpointer user_data)
+{
+ GC_push_all (key, value);
+}
+
+static void
+mono_push_other_roots (void)
+{
+ g_hash_table_foreach (roots, push_root, NULL);
+ if (default_push_other_roots)
+ default_push_other_roots ();
}
static void
obj->vtable = vtable;
}
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
- mono_profiler_allocation (obj);
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+ MONO_PROFILER_RAISE (gc_allocation, (obj));
return obj;
}
obj->max_length = max_length;
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
- mono_profiler_allocation (&obj->obj);
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+ MONO_PROFILER_RAISE (gc_allocation, (&obj->obj));
return obj;
}
if (bounds_size)
obj->bounds = (MonoArrayBounds *) ((char *) obj + size - bounds_size);
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
- mono_profiler_allocation (&obj->obj);
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+ MONO_PROFILER_RAISE (gc_allocation, (&obj->obj));
return obj;
}
obj->length = len;
obj->chars [len] = 0;
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
- mono_profiler_allocation (&obj->object);
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+ MONO_PROFILER_RAISE (gc_allocation, (&obj->object));
return obj;
}
return NULL;
if (mono_class_has_finalizer (klass) || mono_class_is_marshalbyref (klass))
return NULL;
- if (mono_profiler_get_events () & (MONO_PROFILE_ALLOCATIONS | MONO_PROFILE_STATISTICAL))
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
return NULL;
if (klass->rank)
return NULL;
#endif
unlock_handles (handles);
res = MONO_GC_HANDLE (slot, handles->type);
- mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_CREATED, handles->type, res, obj);
+ MONO_PROFILER_RAISE (gc_handle_created, (res, handles->type, obj));
return res;
}
#endif
/*g_print ("freed entry %d of type %d\n", slot, handles->type);*/
unlock_handles (handles);
- mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_DESTROYED, handles->type, gchandle, NULL);
+ MONO_PROFILER_RAISE (gc_handle_deleted, (gchandle, handles->type));
}
/**
klass->name = name;
klass->name_space = nspace;
- mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (class_loading, (klass));
klass->image = image;
klass->type_token = type_token;
/*FIXME implement a mono_class_set_failure_from_mono_error */
mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
mono_loader_unlock ();
- mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (class_failed, (klass));
return NULL;
}
}
mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
mono_loader_unlock ();
- mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (class_failed, (klass));
return NULL;
}
klass->cast_class = klass->element_class = mono_defaults.int32_class;
mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
mono_loader_unlock ();
- mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (class_failed, (klass));
return NULL;
}
klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
mono_loader_unlock ();
- mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (class_failed, (klass));
return NULL;
}
mono_loader_unlock ();
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (class_loaded, (klass));
return klass;
mono_class_setup_mono_type (klass);
mono_loader_unlock ();
- mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (class_failed, (klass));
return NULL;
}
if (mono_class_is_nullable (klass))
klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
- mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (class_loading, (klass));
mono_generic_class_setup_parent (klass, gklass);
mono_memory_barrier ();
gclass->cached_class = klass;
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (class_loaded, (klass));
++class_ginst_count;
inflated_classes_size += sizeof (MonoClassGenericInst);
CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
}
- mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (class_loading, (klass));
// Count non-NULL items in pinfo->constraints
count = 0;
/* FIXME: Should this go inside 'make_generic_param_klass'? */
if (klass2)
- mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
+ MONO_PROFILER_RAISE (class_failed, (klass2));
else
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (class_loaded, (klass));
return klass;
}
result->class_kind = MONO_CLASS_POINTER;
g_free (name);
- mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (class_loading, (result));
result->image = el_class->image;
result->inited = TRUE;
MonoClass *result2;
if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
mono_image_unlock (image);
- mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (class_failed, (result));
return result2;
}
} else {
g_hash_table_insert (image->ptr_cache, el_class, result);
mono_image_unlock (image);
- mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (class_loaded, (result));
return result;
}
return cached;
}
- mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (class_loading, (result));
classes_size += sizeof (MonoClassPointer);
++class_pointer_count;
mono_loader_unlock ();
- mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (class_loaded, (result));
return result;
}
return cached;
}
- mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (class_loading, (klass));
classes_size += sizeof (MonoClassArray);
++class_array_count;
mono_loader_unlock ();
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (class_loaded, (klass));
return klass;
}
*/
image = assembly->image;
+ /* Dynamic images would need to go through the AssemblyBuilder's
+ * CustomAttributeBuilder array. Going through the tables below
+ * definitely won't work. */
g_assert (!image_is_dynamic (image));
idx = 1; /* there is only one assembly */
idx <<= MONO_CUSTOM_ATTR_BITS;
domain->friendly_name = NULL;
domain->search_path = NULL;
- mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (domain_loading, (domain));
domain->mp = mono_mempool_new ();
domain->code_mp = mono_code_manager_new ();
if (create_domain_hook)
create_domain_hook (domain);
- mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (domain_loaded, (domain));
return domain;
}
domain->friendly_name = g_path_get_basename (filename);
- mono_profiler_appdomain_name (domain, domain->friendly_name);
+ MONO_PROFILER_RAISE (domain_name, (domain, domain->friendly_name));
return domain;
}
if (mono_dont_free_domains)
return;
- mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
+ MONO_PROFILER_RAISE (domain_unloading, (domain));
mono_debug_domain_unload (domain);
* Send this after the assemblies have been unloaded and the domain is still in a
* usable state.
*/
- mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
+ MONO_PROFILER_RAISE (domain_unloaded, (domain));
if (free_domain_hook)
free_domain_hook (domain);
domain->setup = NULL;
+#ifndef HAVE_BOEHM_GC
mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
+#endif
mono_appdomains_lock ();
appdomains_list [domain->domain_id] = NULL;
image = g_new0 (MonoDynamicImage, 1);
- mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (image_loading, (&image->image));
/*g_print ("created image %p\n", image);*/
/* keep in sync with image.c */
image->pe_kind = 0x1; /* ILOnly */
image->machine = 0x14c; /* I386 */
- mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (image_loaded, (&image->image));
dynamic_images_lock ();
typedef enum {
// Regular fast path allocator.
MANAGED_ALLOCATOR_REGULAR,
- // Managed allocator that just calls into the runtime. Used when allocation profiling w/ AOT.
+ // Managed allocator that just calls into the runtime.
MANAGED_ALLOCATOR_SLOW_PATH,
+ // Managed allocator that works like the regular one but also calls into the profiler.
+ MANAGED_ALLOCATOR_PROFILER,
} ManagedAllocatorVariant;
int mono_gc_get_aligned_size_for_allocator (int size);
#include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
#include <mono/metadata/attach.h>
#include <mono/metadata/console-io.h>
+#include <mono/metadata/w32process.h>
#include <mono/utils/mono-os-semaphore.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-counters.h>
if (log_finalizers)
g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o);
- mono_profiler_gc_finalize_object_begin (o);
+ MONO_PROFILER_RAISE (gc_finalizing_object, (o));
runtime_invoke (o, NULL, &exc, NULL);
- mono_profiler_gc_finalize_object_end (o);
+ MONO_PROFILER_RAISE (gc_finalized_object, (o));
if (log_finalizers)
g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o);
*
* Notify the finalizer thread that finalizers etc.
* are available to be processed.
+ * This is async signal safe.
*/
void
mono_gc_finalize_notify (void)
finalize_domain_objects ();
- mono_profiler_gc_finalize_begin ();
+ MONO_PROFILER_RAISE (gc_finalizing, ());
/* If finished == TRUE, mono_gc_cleanup has been called (from mono_runtime_cleanup),
* before the domain is unloaded.
*/
mono_gc_invoke_finalizers ();
- mono_profiler_gc_finalize_end ();
+ MONO_PROFILER_RAISE (gc_finalized, ());
mono_threads_join_threads ();
reference_queue_proccess_all ();
+ mono_w32process_signal_finished ();
+
hazard_free_queue_pump ();
/* Avoid posting the pending done event until there are pending finalizers */
GSList *errors = NULL;
GSList *l;
- mono_profiler_module_event (image, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (image_loading, (image));
mono_image_init (image);
load_modules (image);
done:
- mono_profiler_module_loaded (image, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (image_loaded, (image));
if (status)
*status = MONO_IMAGE_OK;
g_warning ("Could not load image %s due to %s", image->name, info->message);
mono_free_verify_list (errors);
}
- mono_profiler_module_loaded (image, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (image_failed, (image));
mono_image_close (image);
return NULL;
}
}
#endif
- mono_profiler_module_event (image, MONO_PROFILE_START_UNLOAD);
+ MONO_PROFILER_RAISE (image_unloading, (image));
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading image %s [%p].", image->name, image);
mono_dynamic_image_free ((MonoDynamicImage*)image);
}
- mono_profiler_module_event (image, MONO_PROFILE_END_UNLOAD);
+ MONO_PROFILER_RAISE (image_unloaded, (image));
return TRUE;
}
#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>
void
mono_free_method (MonoMethod *method)
{
- if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
- mono_profiler_method_free (method);
+ MONO_PROFILER_RAISE (method_free, (method));
/* FIXME: This hack will go away when the profiler will support freeing methods */
- if (mono_profiler_get_events () != MONO_PROFILE_NONE)
+ if (G_UNLIKELY (mono_profiler_installed ()))
return;
if (method->signature) {
csig->call_convention = MONO_CALL_C;
#endif
- name = mono_signature_to_name (callsig, virtual_ ? "runtime_invoke_virtual" : "runtime_invoke");
+ name = mono_signature_to_name (callsig, virtual_ ? "runtime_invoke_virtual" : (need_direct_wrapper ? "runtime_invoke_direct" : "runtime_invoke"));
mb = mono_mb_new (target_klass, name, MONO_WRAPPER_RUNTIME_INVOKE);
g_free (name);
if (virtual_)
need_direct_wrapper = TRUE;
+ if (method->dynamic)
+ need_direct_wrapper = TRUE;
+
if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
(method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
/*
MonoImageSet *
mono_find_image_set_owner (void *ptr);
-void
+MONO_API void
mono_loader_register_module (const char *name, MonoDl *module);
gboolean
return 0;
}
- mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_CONTENTION);
+ MONO_PROFILER_RAISE (monitor_contention, (obj));
/* The slow path begins here. */
retry_contended:
if (G_LIKELY (tmp_status == old_status)) {
/* Success */
g_assert (mon->nest == 1);
- mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_DONE);
+ MONO_PROFILER_RAISE (monitor_acquired, (obj));
return 1;
}
}
/* If the object is currently locked by this thread... */
if (mon_status_get_owner (old_status) == id) {
mon->nest++;
- mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_DONE);
+ MONO_PROFILER_RAISE (monitor_acquired, (obj));
return 1;
}
/* Timed out or interrupted */
mon_decrement_entry_count (mon);
- mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_FAIL);
+ MONO_PROFILER_RAISE (monitor_failed, (obj));
if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
LOCK_DEBUG (g_message ("%s: (%d) interrupted waiting, returning -1", __func__, id));
MONO_ROOT_SOURCE_HANDLE = 14,
} MonoGCRootSource;
+typedef enum {
+ MONO_GC_HANDLE_TYPE_MIN = 0,
+ MONO_GC_HANDLE_WEAK = MONO_GC_HANDLE_TYPE_MIN,
+ MONO_GC_HANDLE_WEAK_TRACK_RESURRECTION,
+ MONO_GC_HANDLE_NORMAL,
+ MONO_GC_HANDLE_PINNED,
+ MONO_GC_HANDLE_TYPE_MAX,
+} MonoGCHandleType;
+
MONO_API void mono_gc_collect (int generation);
MONO_API int mono_gc_max_generation (void);
MONO_API int mono_gc_get_generation (MonoObject *object);
error_init (error);
- if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
- mono_profiler_method_start_invoke (method);
+ MONO_PROFILER_RAISE (method_begin_invoke, (method));
result = callbacks.runtime_invoke (method, obj, params, exc, error);
- if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
- mono_profiler_method_end_invoke (method);
+ MONO_PROFILER_RAISE (method_end_invoke, (method));
if (!mono_error_ok (error))
return NULL;
--- /dev/null
+/*
+ * 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.
+ */
+
+/*
+ * To #include this file, #define the following macros first:
+ *
+ * MONO_PROFILER_EVENT_0(name, type)
+ * MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name)
+ * MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name)
+ * MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name)
+ * MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name)
+ *
+ * To add new callbacks to the API, simply add a line in this file and use
+ * MONO_PROFILER_RAISE to raise the event wherever. If you need more arguments
+ * then the current macros provide, add another macro and update all areas
+ * where the macros are used.
+ */
+
+MONO_PROFILER_EVENT_0(runtime_initialized, RuntimeInitialized)
+MONO_PROFILER_EVENT_0(runtime_shutdown_begin, RuntimeShutdownBegin)
+MONO_PROFILER_EVENT_0(runtime_shutdown_end, RuntimeShutdownEnd)
+
+MONO_PROFILER_EVENT_1(context_loaded, ContextLoaded, MonoAppContext *, context)
+MONO_PROFILER_EVENT_1(context_unloaded, ContextUnloaded, MonoAppContext *, context)
+
+MONO_PROFILER_EVENT_1(domain_loading, DomainLoading, MonoDomain *, domain)
+MONO_PROFILER_EVENT_1(domain_loaded, DomainLoaded, MonoDomain *, domain)
+MONO_PROFILER_EVENT_1(domain_unloading, DomainUnloading, MonoDomain *, domain)
+MONO_PROFILER_EVENT_1(domain_unloaded, DomainUnloaded, MonoDomain *, domain)
+MONO_PROFILER_EVENT_2(domain_name, DomainName, MonoDomain *, domain, const char *, name)
+
+MONO_PROFILER_EVENT_1(jit_begin, JitBegin, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(jit_failed, JitFailed, MonoMethod *, method)
+MONO_PROFILER_EVENT_2(jit_done, JitDone, MonoMethod *, method, MonoJitInfo *, jinfo)
+MONO_PROFILER_EVENT_2(jit_chunk_created, JitChunkCreated, const mono_byte *, chunk, uintptr_t, size)
+MONO_PROFILER_EVENT_1(jit_chunk_destroyed, JitChunkDestroyed, const mono_byte *, chunk)
+MONO_PROFILER_EVENT_4(jit_code_buffer, JitCodeBuffer, const mono_byte *, buffer, uint64_t, size, MonoProfilerCodeBufferType, type, const void *, data)
+
+MONO_PROFILER_EVENT_1(class_loading, ClassLoading, MonoClass *, klass)
+MONO_PROFILER_EVENT_1(class_failed, ClassFailed, MonoClass *, klass)
+MONO_PROFILER_EVENT_1(class_loaded, ClassLoaded, MonoClass *, klass)
+
+MONO_PROFILER_EVENT_1(image_loading, ModuleLoading, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_failed, ModuleFailed, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_loaded, ModuleLoaded, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_unloading, ModuleUnloading, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_unloaded, ModuleUnloaded, MonoImage *, image)
+
+MONO_PROFILER_EVENT_1(assembly_loading, AssemblyLoading, MonoAssembly *, assembly)
+MONO_PROFILER_EVENT_1(assembly_loaded, AssemblyLLoaded, MonoAssembly *, assembly)
+MONO_PROFILER_EVENT_1(assembly_unloading, AssemblyLUnloading, MonoAssembly *, assembly)
+MONO_PROFILER_EVENT_1(assembly_unloaded, AssemblyLUnloaded, MonoAssembly *, assembly)
+
+MONO_PROFILER_EVENT_1(method_enter, MethodEnter, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(method_leave, MethodLeave, MonoMethod *, method)
+MONO_PROFILER_EVENT_2(method_exception_leave, MethodExceptionLeave, MonoMethod *, method, MonoObject *, exception)
+MONO_PROFILER_EVENT_1(method_free, MethodFree, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(method_begin_invoke, MethodBeginInvoke, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(method_end_invoke, MethodEndInvoke, MonoMethod *, method)
+
+MONO_PROFILER_EVENT_1(exception_throw, ExceptionThrow, MonoObject *, exception)
+MONO_PROFILER_EVENT_4(exception_clause, ExceptionClause, MonoMethod *, method, uint32_t, index, MonoExceptionEnum, type, MonoObject *, exception)
+
+MONO_PROFILER_EVENT_2(gc_event, GCEvent, MonoProfilerGCEvent, event, uint32_t, generation)
+MONO_PROFILER_EVENT_1(gc_allocation, GCAllocation, MonoObject *, object)
+MONO_PROFILER_EVENT_2(gc_moves, GCMoves, MonoObject *const *, objects, uint64_t, count)
+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_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)
+
+MONO_PROFILER_EVENT_1(thread_started, ThreadStarted, uintptr_t, tid)
+MONO_PROFILER_EVENT_1(thread_stopped, ThreadStopped, uintptr_t, tid)
+MONO_PROFILER_EVENT_2(thread_name, ThreadName, uintptr_t, tid, const char *, name)
+
+MONO_PROFILER_EVENT_2(sample_hit, SampleHit, const mono_byte *, ip, const void *, context)
+
+MONO_PROFILER_EVENT_3(iomap_report, IOMap, const char *, report, const char *, old_path, const char *, new_path)
-/**
- * \file
+/*
+ * 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.
*/
#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-compiler.h"
-#include <glib.h>
-
-extern MonoProfileFlags mono_profiler_events;
-
-enum {
- MONO_PROFILE_START_LOAD,
- MONO_PROFILE_END_LOAD,
- MONO_PROFILE_START_UNLOAD,
- MONO_PROFILE_END_UNLOAD
+#include <mono/utils/mono-lazy-init.h>
+#include <mono/utils/mono-os-mutex.h>
+#include <mono/utils/mono-os-semaphore.h>
+
+struct _MonoProfilerDesc {
+ MonoProfilerHandle next;
+ MonoProfiler *prof;
+ volatile gpointer coverage_filter;
+ volatile gpointer call_instrumentation_filter;
+
+#define _MONO_PROFILER_EVENT(name) \
+ volatile gpointer name ## _cb;
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
};
typedef struct {
- int entries;
- struct {
- guchar* cil_code;
- int count;
- } data [1];
-} MonoProfileCoverageInfo;
-
-void mono_profiler_shutdown (void);
-
-void mono_profiler_method_enter (MonoMethod *method);
-void mono_profiler_method_leave (MonoMethod *method);
-void mono_profiler_method_jit (MonoMethod *method);
-void mono_profiler_method_end_jit (MonoMethod *method, MonoJitInfo* jinfo, int result);
-void mono_profiler_method_free (MonoMethod *method);
-void mono_profiler_method_start_invoke (MonoMethod *method);
-void mono_profiler_method_end_invoke (MonoMethod *method);
-
-void mono_profiler_code_transition (MonoMethod *method, int result);
-void mono_profiler_allocation (MonoObject *obj);
-void mono_profiler_monitor_event (MonoObject *obj, MonoProfilerMonitorEvent event);
-void mono_profiler_stat_hit (guchar *ip, void *context);
-void mono_profiler_stat_call_chain (int call_chain_depth, guchar **ips, void *context);
-int mono_profiler_stat_get_call_chain_depth (void);
-MonoProfilerCallChainStrategy mono_profiler_stat_get_call_chain_strategy (void);
-void mono_profiler_thread_start (gsize tid);
-void mono_profiler_thread_end (gsize tid);
-void mono_profiler_thread_name (gsize tid, const char *name);
-
-void mono_profiler_exception_thrown (MonoObject *exception);
-void mono_profiler_exception_method_leave (MonoMethod *method);
-void mono_profiler_exception_clause_handler (MonoMethod *method, int clause_type, int clause_num, MonoObject *exc);
-
-void mono_profiler_assembly_event (MonoAssembly *assembly, int code);
-void mono_profiler_assembly_loaded (MonoAssembly *assembly, int result);
-
-void mono_profiler_module_event (MonoImage *image, int code);
-void mono_profiler_module_loaded (MonoImage *image, int result);
-
-void mono_profiler_class_event (MonoClass *klass, int code);
-void mono_profiler_class_loaded (MonoClass *klass, int result);
-
-void mono_profiler_appdomain_event (MonoDomain *domain, int code);
-void mono_profiler_appdomain_loaded (MonoDomain *domain, int result);
-void mono_profiler_appdomain_name (MonoDomain *domain, const char *name);
-
-void mono_profiler_context_loaded (MonoAppContext *context);
-void mono_profiler_context_unloaded (MonoAppContext *context);
-
-void mono_profiler_iomap (char *report, const char *pathname, const char *new_pathname);
-
-MonoProfileCoverageInfo* mono_profiler_coverage_alloc (MonoMethod *method, int entries);
-void mono_profiler_coverage_free (MonoMethod *method);
-
-void mono_profiler_gc_event (MonoGCEvent e, int generation);
-void mono_profiler_gc_heap_resize (gint64 new_size);
-void mono_profiler_gc_moves (void **objects, int num);
-void mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj);
-void mono_profiler_gc_roots (int num, void **objects, int *root_types, uintptr_t *extra_info);
-
-void mono_profiler_gc_finalize_begin (void);
-void mono_profiler_gc_finalize_object_begin (MonoObject *obj);
-void mono_profiler_gc_finalize_object_end (MonoObject *obj);
-void mono_profiler_gc_finalize_end (void);
-
-void mono_profiler_code_chunk_new (gpointer chunk, int size);
-void mono_profiler_code_chunk_destroy (gpointer chunk);
-void mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, gconstpointer data);
-
-void mono_profiler_runtime_initialized (void);
-
-int64_t mono_profiler_get_sampling_rate (void);
-MonoProfileSamplingMode mono_profiler_get_sampling_mode (void);
-
-#endif /* __MONO_PROFILER_PRIVATE_H__ */
+ gboolean startup_done;
+ MonoProfilerHandle profilers;
+ mono_lazy_init_t coverage_status;
+ mono_mutex_t coverage_mutex;
+ GHashTable *coverage_hash;
+ MonoProfilerHandle sampling_owner;
+ MonoSemType sampling_semaphore;
+ MonoProfilerSampleMode sample_mode;
+ guint32 sample_freq;
+ gboolean allocations;
+
+#define _MONO_PROFILER_EVENT(name) \
+ volatile gint32 name ## _count;
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+} MonoProfilerState;
+
+extern MonoProfilerState mono_profiler_state;
+typedef struct {
+ guint32 entries;
+ struct {
+ guchar *cil_code;
+ guint32 count;
+ } data [1];
+} MonoProfilerCoverageInfo;
+
+void mono_profiler_started (void);
+void mono_profiler_cleanup (void);
+
+static inline gboolean
+mono_profiler_installed (void)
+{
+ return !!mono_profiler_state.profilers;
+}
+
+MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries);
+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_post (void);
+void mono_profiler_sampling_thread_wait (void);
+
+static inline gboolean
+mono_profiler_allocations_enabled (void)
+{
+ return mono_profiler_state.allocations;
+}
+
+#define _MONO_PROFILER_EVENT(name, ...) \
+ void mono_profiler_raise_ ## name (__VA_ARGS__);
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name, void)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name, arg1_type arg1_name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+
+// These are the macros the rest of the runtime should use.
+
+#define MONO_PROFILER_ENABLED(name) \
+ G_UNLIKELY (mono_profiler_state.name ## _count)
+
+#define MONO_PROFILER_RAISE(name, args) \
+ do { \
+ if (MONO_PROFILER_ENABLED (name)) \
+ mono_profiler_raise_ ## name args; \
+ } while (0)
+
+#endif // __MONO_PROFILER_PRIVATE_H__
-/**
- * \file
- * Profiler interface for Mono
- *
- * Author:
- * Paolo Molaro (lupus@ximian.com)
- * Alex Rønne Petersen (alexrp@xamarin.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include "config.h"
-#include "mono/metadata/profiler-private.h"
-#include "mono/metadata/assembly.h"
-#include "mono/metadata/debug-helpers.h"
-#include "mono/metadata/mono-debug.h"
-#include "mono/metadata/debug-internals.h"
-#include "mono/metadata/metadata-internals.h"
-#include "mono/metadata/class-internals.h"
-#include "mono/metadata/domain-internals.h"
-#include "mono/metadata/gc-internals.h"
-#include "mono/metadata/mono-config-dirs.h"
-#include "mono/utils/mono-dl.h"
+/*
+ * 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.
+ */
+
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/metadata/mono-config-dirs.h>
+#include <mono/metadata/mono-debug.h>
+#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>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_BACKTRACE_SYMBOLS
-#include <execinfo.h>
-#endif
-
-typedef struct _ProfilerDesc ProfilerDesc;
-struct _ProfilerDesc {
- ProfilerDesc *next;
- MonoProfiler *profiler;
- MonoProfileFlags events;
-
- MonoProfileAppDomainFunc domain_start_load;
- MonoProfileAppDomainResult domain_end_load;
- MonoProfileAppDomainFunc domain_start_unload;
- MonoProfileAppDomainFunc domain_end_unload;
- MonoProfileAppDomainFriendlyNameFunc domain_name;
-
- MonoProfileContextFunc context_load;
- MonoProfileContextFunc context_unload;
-
- MonoProfileAssemblyFunc assembly_start_load;
- MonoProfileAssemblyResult assembly_end_load;
- MonoProfileAssemblyFunc assembly_start_unload;
- MonoProfileAssemblyFunc assembly_end_unload;
-
- MonoProfileModuleFunc module_start_load;
- MonoProfileModuleResult module_end_load;
- MonoProfileModuleFunc module_start_unload;
- MonoProfileModuleFunc module_end_unload;
-
- MonoProfileClassFunc class_start_load;
- MonoProfileClassResult class_end_load;
- MonoProfileClassFunc class_start_unload;
- MonoProfileClassFunc class_end_unload;
-
- MonoProfileMethodFunc jit_start;
- MonoProfileMethodResult jit_end;
- MonoProfileJitResult jit_end2;
- MonoProfileMethodFunc method_free;
- MonoProfileMethodFunc method_start_invoke;
- MonoProfileMethodFunc method_end_invoke;
- MonoProfileMethodResult man_unman_transition;
- MonoProfileAllocFunc allocation_cb;
- MonoProfileMonitorFunc monitor_event_cb;
- MonoProfileStatFunc statistical_cb;
- MonoProfileStatCallChainFunc statistical_call_chain_cb;
- int statistical_call_chain_depth;
- MonoProfilerCallChainStrategy statistical_call_chain_strategy;
- MonoProfileMethodFunc method_enter;
- MonoProfileMethodFunc method_leave;
-
- MonoProfileExceptionFunc exception_throw_cb;
- MonoProfileMethodFunc exception_method_leave_cb;
- MonoProfileExceptionClauseFunc exception_clause_cb;
- MonoProfileExceptionClauseFunc2 exception_clause_cb2;
-
- MonoProfileIomapFunc iomap_cb;
-
- MonoProfileThreadFunc thread_start;
- MonoProfileThreadFunc thread_end;
- MonoProfileThreadNameFunc thread_name;
-
- MonoProfileCoverageFilterFunc coverage_filter_cb;
-
- MonoProfileFunc shutdown_callback;
-
- MonoProfileGCFunc gc_event;
- MonoProfileGCResizeFunc gc_heap_resize;
- MonoProfileGCMoveFunc gc_moves;
- MonoProfileGCHandleFunc gc_handle;
- MonoProfileGCRootFunc gc_roots;
-
- MonoProfileGCFinalizeFunc gc_finalize_begin;
- MonoProfileGCFinalizeObjectFunc gc_finalize_object_begin;
- MonoProfileGCFinalizeObjectFunc gc_finalize_object_end;
- MonoProfileGCFinalizeFunc gc_finalize_end;
-
- MonoProfileFunc runtime_initialized_event;
-
- MonoProfilerCodeChunkNew code_chunk_new;
- MonoProfilerCodeChunkDestroy code_chunk_destroy;
- MonoProfilerCodeBufferNew code_buffer_new;
-};
-
-static ProfilerDesc *prof_list = NULL;
-
-#define mono_profiler_coverage_lock() mono_os_mutex_lock (&profiler_coverage_mutex)
-#define mono_profiler_coverage_unlock() mono_os_mutex_unlock (&profiler_coverage_mutex)
-static mono_mutex_t profiler_coverage_mutex;
-
-/* this is directly accessible to other mono libs.
- * It is the ORed value of all the profiler's events.
- */
-MonoProfileFlags mono_profiler_events;
-
-/**
- * mono_profiler_install:
- * \param prof a \c MonoProfiler structure pointer, or a pointer to a derived structure.
- * \param callback the function to invoke at shutdown
- * Use \c mono_profiler_install to activate profiling in the Mono runtime.
- * Typically developers of new profilers will create a new structure whose
- * first field is a \c MonoProfiler and put any extra information that they need
- * to access from the various profiling callbacks there.
- */
-void
-mono_profiler_install (MonoProfiler *prof, MonoProfileFunc callback)
-{
- ProfilerDesc *desc = g_new0 (ProfilerDesc, 1);
- if (!prof_list)
- mono_os_mutex_init_recursive (&profiler_coverage_mutex);
- desc->profiler = prof;
- desc->shutdown_callback = callback;
- desc->next = prof_list;
- prof_list = desc;
-}
-/**
- * mono_profiler_set_events:
- * \param events an ORed set of values made up of \c MONO_PROFILER_ flags
- * The events described in the \p events argument is a set of flags
- * that represent which profiling events must be triggered. For
- * example if you have registered a set of methods for tracking
- * JIT compilation start and end with \c mono_profiler_install_jit_compile,
- * you will want to pass the \c MONO_PROFILE_JIT_COMPILATION flag to
- * this routine.
- *
- * You can call \c mono_profile_set_events more than once and you can
- * do this at runtime to modify which methods are invoked.
- */
-void
-mono_profiler_set_events (MonoProfileFlags events)
-{
- ProfilerDesc *prof;
- MonoProfileFlags value = (MonoProfileFlags)0;
- if (prof_list)
- prof_list->events = events;
- for (prof = prof_list; prof; prof = prof->next)
- value = (MonoProfileFlags)(value | prof->events);
- mono_profiler_events = value;
-}
+MonoProfilerState mono_profiler_state;
-/**
- * mono_profiler_get_events:
- *
- * Returns a list of active events that will be intercepted.
- */
-MonoProfileFlags
-mono_profiler_get_events (void)
-{
- return mono_profiler_events;
-}
+typedef void (*MonoProfilerInitializer) (const char *);
-/**
- * mono_profiler_install_enter_leave:
- * \param enter the routine to be called on each method entry
- * \param fleave the routine to be called each time a method returns
- *
- * Use this routine to install routines that will be called everytime
- * a method enters and leaves. The routines will receive as an argument
- * the \c MonoMethod representing the method that is entering or leaving.
- */
-void
-mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave)
-{
- if (!prof_list)
- return;
- prof_list->method_enter = enter;
- prof_list->method_leave = fleave;
-}
+#define OLD_INITIALIZER_NAME "mono_profiler_startup"
+#define NEW_INITIALIZER_NAME "mono_profiler_init"
-/**
- * mono_profiler_install_jit_compile:
- * \param start the routine to be called when the JIT process starts.
- * \param end the routine to be called when the JIT process ends.
- *
- * Use this routine to install routines that will be called when JIT
- * compilation of a method starts and completes.
- */
-void
-mono_profiler_install_jit_compile (MonoProfileMethodFunc start, MonoProfileMethodResult end)
+static gboolean
+load_profiler (MonoDl *module, const char *name, const char *desc)
{
- if (!prof_list)
- return;
- prof_list->jit_start = start;
- prof_list->jit_end = end;
-}
+ if (!module)
+ return FALSE;
-void
-mono_profiler_install_jit_end (MonoProfileJitResult end)
-{
- if (!prof_list)
- return;
- prof_list->jit_end2 = end;
-}
+ char *err, *old_name = g_strdup_printf (OLD_INITIALIZER_NAME);
+ MonoProfilerInitializer func;
-void
-mono_profiler_install_method_free (MonoProfileMethodFunc callback)
-{
- if (!prof_list)
- return;
- prof_list->method_free = callback;
-}
+ if (!(err = mono_dl_symbol (module, old_name, (gpointer) &func))) {
+ mono_profiler_printf_err ("Found old-style startup symbol '%s' for the '%s' profiler; it has not been migrated to the new API.", old_name, name);
+ g_free (old_name);
+ return FALSE;
+ }
-void
-mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end)
-{
- if (!prof_list)
- return;
- prof_list->method_start_invoke = start;
- prof_list->method_end_invoke = end;
-}
+ g_free (err);
+ g_free (old_name);
-/**
- * mono_profiler_install_thread:
- */
-void
-mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end)
-{
- if (!prof_list)
- return;
- prof_list->thread_start = start;
- prof_list->thread_end = end;
-}
+ char *new_name = g_strdup_printf (NEW_INITIALIZER_NAME "_%s", name);
-void
-mono_profiler_install_thread_name (MonoProfileThreadNameFunc thread_name_cb)
-{
- if (!prof_list)
- return;
- prof_list->thread_name = thread_name_cb;
-}
+ if ((err = mono_dl_symbol (module, new_name, (gpointer *) &func))) {
+ g_free (err);
+ g_free (new_name);
+ return FALSE;
+ }
-/**
- * mono_profiler_install_transition:
- */
-void
-mono_profiler_install_transition (MonoProfileMethodResult callback)
-{
- if (!prof_list)
- return;
- prof_list->man_unman_transition = callback;
-}
+ g_free (new_name);
-/**
- * mono_profiler_install_allocation:
- */
-void
-mono_profiler_install_allocation (MonoProfileAllocFunc callback)
-{
- if (!prof_list)
- return;
- prof_list->allocation_cb = callback;
-}
+ func (desc);
-void
-mono_profiler_install_monitor (MonoProfileMonitorFunc callback)
-{
- if (!prof_list)
- return;
- prof_list->monitor_event_cb = callback;
+ return TRUE;
}
-static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
-static int64_t sampling_frequency = 100; // Hz
-
-/**
- * mono_profiler_set_statistical_mode:
- * \param mode the sampling mode used.
- * \param sample_frequency_is_us the sampling frequency in microseconds.
- *
- * Set the sampling parameters for the profiler. Sampling mode affects the effective sampling rate as in samples/s you'll witness.
- * The default sampling mode is process mode, which only reports samples when there's activity in the process.
- *
- * Sampling frequency should be interpreted as a suggestion that can't always be honored due to how most kernels expose alarms.
- *
- * Said that, when using statistical sampling, always assume variable rate sampling as all sort of external factors can interfere.
- */
-void
-mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_hz)
+static gboolean
+load_profiler_from_executable (const char *name, const char *desc)
{
- sampling_mode = mode;
- sampling_frequency = sampling_frequency_hz;
-}
+ char *err;
-/**
- * mono_profiler_install_statistical:
- */
-void
-mono_profiler_install_statistical (MonoProfileStatFunc callback)
-{
- if (!prof_list)
- return;
- prof_list->statistical_cb = callback;
-}
+ /*
+ * Some profilers (such as ours) may need to call back into the runtime
+ * from their sampling callback (which is called in async-signal context).
+ * They need to be able to know that all references back to the runtime
+ * have been resolved; otherwise, calling runtime functions may result in
+ * invoking the dynamic linker which is not async-signal-safe. Passing
+ * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront.
+ */
+ MonoDl *module = mono_dl_open (NULL, MONO_DL_EAGER, &err);
-int64_t
-mono_profiler_get_sampling_rate (void)
-{
- return sampling_frequency;
+ if (!module) {
+ mono_profiler_printf_err ("Could not open main executable: %s", err);
+ g_free (err);
+ return FALSE;
+ }
+
+ return load_profiler (module, name, desc);
}
-MonoProfileSamplingMode
-mono_profiler_get_sampling_mode (void)
+static gboolean
+load_profiler_from_directory (const char *directory, const char *libname, const char *name, const char *desc)
{
- return sampling_mode;
-}
+ char* path;
+ void *iter = NULL;
-void
-mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy) {
- if (!prof_list)
- return;
- if (call_chain_depth > MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH) {
- call_chain_depth = MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH;
- }
- if ((call_chain_strategy >= MONO_PROFILER_CALL_CHAIN_INVALID) || (call_chain_strategy < MONO_PROFILER_CALL_CHAIN_NONE)) {
- call_chain_strategy = MONO_PROFILER_CALL_CHAIN_NONE;
- }
- prof_list->statistical_call_chain_cb = callback;
- prof_list->statistical_call_chain_depth = call_chain_depth;
- prof_list->statistical_call_chain_strategy = call_chain_strategy;
-}
+ while ((path = mono_dl_build_path (directory, libname, &iter))) {
+ // See the comment in load_embedded_profiler ().
+ MonoDl *module = mono_dl_open (path, MONO_DL_EAGER, NULL);
-int
-mono_profiler_stat_get_call_chain_depth (void) {
- if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
- return prof_list->statistical_call_chain_depth;
- } else {
- return 0;
- }
-}
+ g_free (path);
-MonoProfilerCallChainStrategy
-mono_profiler_stat_get_call_chain_strategy (void) {
- if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
- return prof_list->statistical_call_chain_strategy;
- } else {
- return MONO_PROFILER_CALL_CHAIN_NONE;
+ if (module)
+ return load_profiler (module, name, desc);
}
-}
-void mono_profiler_install_exception (MonoProfileExceptionFunc throw_callback, MonoProfileMethodFunc exc_method_leave, MonoProfileExceptionClauseFunc clause_callback)
-{
- if (!prof_list)
- return;
- prof_list->exception_throw_cb = throw_callback;
- prof_list->exception_method_leave_cb = exc_method_leave;
- prof_list->exception_clause_cb = clause_callback;
+ return FALSE;
}
-void mono_profiler_install_exception_clause (MonoProfileExceptionClauseFunc2 clause_callback)
+static gboolean
+load_profiler_from_installation (const char *libname, const char *name, const char *desc)
{
- if (!prof_list)
- return;
-
- prof_list->exception_clause_cb2 = clause_callback;
-}
+ char *err;
+ MonoDl *module = mono_dl_open_runtime_lib (libname, MONO_DL_EAGER, &err);
-/**
- * mono_profiler_install_coverage_filter:
- */
-void
-mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback)
-{
- if (!prof_list)
- return;
- prof_list->coverage_filter_cb = callback;
-}
+ g_free (err);
-/**
- * mono_profiler_install_appdomain:
- */
-void
-mono_profiler_install_appdomain (MonoProfileAppDomainFunc start_load, MonoProfileAppDomainResult end_load,
- MonoProfileAppDomainFunc start_unload, MonoProfileAppDomainFunc end_unload)
+ if (module)
+ return load_profiler (module, name, desc);
-{
- if (!prof_list)
- return;
- prof_list->domain_start_load = start_load;
- prof_list->domain_end_load = end_load;
- prof_list->domain_start_unload = start_unload;
- prof_list->domain_end_unload = end_unload;
+ return FALSE;
}
void
-mono_profiler_install_appdomain_name (MonoProfileAppDomainFriendlyNameFunc domain_name_cb)
+mono_profiler_load (const char *desc)
{
- if (!prof_list)
- return;
+ if (!desc || !strcmp ("default", desc))
+ desc = "log:report";
- prof_list->domain_name = domain_name_cb;
-}
+ const char *col = strchr (desc, ':');
+ char *mname;
-void
-mono_profiler_install_context (MonoProfileContextFunc load, MonoProfileContextFunc unload)
-{
- if (!prof_list)
- return;
+ if (col != NULL) {
+ mname = (char *) g_memdup (desc, col - desc + 1);
+ mname [col - desc] = 0;
+ } else
+ mname = g_strdup (desc);
- prof_list->context_load = load;
- prof_list->context_unload = unload;
-}
+ if (!load_profiler_from_executable (mname, desc)) {
+ char *libname = g_strdup_printf ("mono-profiler-%s", mname);
+ gboolean res = load_profiler_from_installation (libname, mname, desc);
-/**
- * mono_profiler_install_assembly:
- */
-void
-mono_profiler_install_assembly (MonoProfileAssemblyFunc start_load, MonoProfileAssemblyResult end_load,
- MonoProfileAssemblyFunc start_unload, MonoProfileAssemblyFunc end_unload)
-{
- if (!prof_list)
- return;
- prof_list->assembly_start_load = start_load;
- prof_list->assembly_end_load = end_load;
- prof_list->assembly_start_unload = start_unload;
- prof_list->assembly_end_unload = end_unload;
-}
+ if (!res && mono_config_get_assemblies_dir ())
+ res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, mname, desc);
-/**
- * mono_profiler_install_module:
- */
-void
-mono_profiler_install_module (MonoProfileModuleFunc start_load, MonoProfileModuleResult end_load,
- MonoProfileModuleFunc start_unload, MonoProfileModuleFunc end_unload)
-{
- if (!prof_list)
- return;
- prof_list->module_start_load = start_load;
- prof_list->module_end_load = end_load;
- prof_list->module_start_unload = start_unload;
- prof_list->module_end_unload = end_unload;
-}
+ if (!res)
+ res = load_profiler_from_directory (NULL, libname, mname, desc);
-/**
- * mono_profiler_install_class:
- */
-void
-mono_profiler_install_class (MonoProfileClassFunc start_load, MonoProfileClassResult end_load,
- MonoProfileClassFunc start_unload, MonoProfileClassFunc end_unload)
-{
- if (!prof_list)
- return;
- prof_list->class_start_load = start_load;
- prof_list->class_end_load = end_load;
- prof_list->class_start_unload = start_unload;
- prof_list->class_end_unload = end_unload;
-}
+ if (!res)
+ mono_profiler_printf_err ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname);
-/**
- * mono_profiler_method_enter:
- */
-void
-mono_profiler_method_enter (MonoMethod *method)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_enter)
- prof->method_enter (prof->profiler, method);
+ g_free (libname);
}
-}
-/**
- * mono_profiler_method_leave:
- */
-void
-mono_profiler_method_leave (MonoMethod *method)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_leave)
- prof->method_leave (prof->profiler, method);
- }
+ g_free (mname);
}
-/**
- * mono_profiler_method_jit:
- */
-void
-mono_profiler_method_jit (MonoMethod *method)
+MonoProfilerHandle
+mono_profiler_install (MonoProfiler *prof)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_JIT_COMPILATION) && prof->jit_start)
- prof->jit_start (prof->profiler, method);
- }
-}
+ MonoProfilerHandle handle = g_new0 (struct _MonoProfilerDesc, 1);
-/**
- * mono_profiler_method_end_jit:
- */
-void
-mono_profiler_method_end_jit (MonoMethod *method, MonoJitInfo* jinfo, int result)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_JIT_COMPILATION)) {
- if (prof->jit_end)
- prof->jit_end (prof->profiler, method, result);
- if (prof->jit_end2)
- prof->jit_end2 (prof->profiler, method, jinfo, result);
- }
- }
-}
+ handle->prof = prof;
+ handle->next = mono_profiler_state.profilers;
-void
-mono_profiler_method_free (MonoMethod *method)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_free)
- prof->method_free (prof->profiler, method);
- }
-}
+ mono_profiler_state.profilers = handle;
-void
-mono_profiler_method_start_invoke (MonoMethod *method)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_start_invoke)
- prof->method_start_invoke (prof->profiler, method);
- }
+ return handle;
}
void
-mono_profiler_method_end_invoke (MonoMethod *method)
+mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_end_invoke)
- prof->method_end_invoke (prof->profiler, method);
- }
+ InterlockedWritePointer (&handle->coverage_filter, (gpointer) cb);
}
-/**
- * mono_profiler_code_transition:
- */
-void
-mono_profiler_code_transition (MonoMethod *method, int result)
+static void
+initialize_coverage (void)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_TRANSITIONS) && prof->man_unman_transition)
- prof->man_unman_transition (prof->profiler, method, result);
- }
+ mono_os_mutex_init (&mono_profiler_state.coverage_mutex);
+ mono_profiler_state.coverage_hash = g_hash_table_new (NULL, NULL);
}
-/**
- * mono_profiler_allocation:
- */
-void
-mono_profiler_allocation (MonoObject *obj)
+static void
+lazy_initialize_coverage (void)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_ALLOCATIONS) && prof->allocation_cb)
- prof->allocation_cb (prof->profiler, obj, obj->vtable->klass);
- }
+ mono_lazy_initialize (&mono_profiler_state.coverage_status, initialize_coverage);
}
-void
-mono_profiler_monitor_event (MonoObject *obj, MonoProfilerMonitorEvent event) {
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_MONITOR_EVENTS) && prof->monitor_event_cb)
- prof->monitor_event_cb (prof->profiler, obj, event);
- }
-}
-
-/**
- * mono_profiler_stat_hit:
- */
-void
-mono_profiler_stat_hit (guchar *ip, void *context)
+static void
+coverage_lock (void)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_cb)
- prof->statistical_cb (prof->profiler, ip, context);
- }
+ mono_os_mutex_lock (&mono_profiler_state.coverage_mutex);
}
-void
-mono_profiler_stat_call_chain (int call_chain_depth, guchar **ips, void *context)
+static void
+coverage_unlock (void)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_call_chain_cb)
- prof->statistical_call_chain_cb (prof->profiler, call_chain_depth, ips, context);
- }
+ mono_os_mutex_unlock (&mono_profiler_state.coverage_mutex);
}
void
-mono_profiler_exception_thrown (MonoObject *exception)
+mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_throw_cb)
- prof->exception_throw_cb (prof->profiler, exception);
- }
-}
+ lazy_initialize_coverage ();
-void
-mono_profiler_exception_method_leave (MonoMethod *method)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_method_leave_cb)
- prof->exception_method_leave_cb (prof->profiler, method);
- }
-}
+ coverage_lock ();
-void
-mono_profiler_exception_clause_handler (MonoMethod *method, int clause_type, int clause_num, MonoObject *exc)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (prof->events & MONO_PROFILE_EXCEPTIONS) {
- if (prof->exception_clause_cb)
- prof->exception_clause_cb (prof->profiler, method, clause_type, clause_num);
-
- if (prof->exception_clause_cb2)
- prof->exception_clause_cb2 (prof->profiler, method, clause_type, clause_num, exc);
- }
- }
-}
+ MonoProfilerCoverageInfo *info = g_hash_table_lookup (mono_profiler_state.coverage_hash, method);
-/**
- * mono_profiler_thread_start:
- */
-void
-mono_profiler_thread_start (gsize tid)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_start)
- prof->thread_start (prof->profiler, tid);
- }
-}
+ coverage_unlock ();
-/**
- * mono_profiler_thread_end:
- */
-void
-mono_profiler_thread_end (gsize tid)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_end)
- prof->thread_end (prof->profiler, tid);
- }
-}
+ if (!info)
+ return;
-void
-mono_profiler_thread_name (gsize tid, const char *name)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_name)
- prof->thread_name (prof->profiler, tid, name);
- }
-}
+ MonoError error;
+ MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
+ mono_error_assert_ok (&error);
-/**
- * mono_profiler_assembly_event:
- */
-void
-mono_profiler_assembly_event (MonoAssembly *assembly, int code)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (!(prof->events & MONO_PROFILE_ASSEMBLY_EVENTS))
- continue;
-
- switch (code) {
- case MONO_PROFILE_START_LOAD:
- if (prof->assembly_start_load)
- prof->assembly_start_load (prof->profiler, assembly);
- break;
- case MONO_PROFILE_START_UNLOAD:
- if (prof->assembly_start_unload)
- prof->assembly_start_unload (prof->profiler, assembly);
- break;
- case MONO_PROFILE_END_UNLOAD:
- if (prof->assembly_end_unload)
- prof->assembly_end_unload (prof->profiler, assembly);
- break;
- default:
- g_assert_not_reached ();
- }
- }
-}
+ guint32 size;
-/**
- * mono_profiler_assembly_loaded:
- */
-void
-mono_profiler_assembly_loaded (MonoAssembly *assembly, int result)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_ASSEMBLY_EVENTS) && prof->assembly_end_load)
- prof->assembly_end_load (prof->profiler, assembly, result);
- }
-}
+ const unsigned char *start = mono_method_header_get_code (header, &size, NULL);
+ const unsigned char *end = start - size;
+ MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method);
-void mono_profiler_iomap (char *report, const char *pathname, const char *new_pathname)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_IOMAP_EVENTS) && prof->iomap_cb)
- prof->iomap_cb (prof->profiler, report, pathname, new_pathname);
- }
-}
+ for (guint32 i = 0; i < info->entries; i++) {
+ guchar *cil_code = info->data [i].cil_code;
-/**
- * mono_profiler_module_event:
- */
-void
-mono_profiler_module_event (MonoImage *module, int code)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (!(prof->events & MONO_PROFILE_MODULE_EVENTS))
- continue;
-
- switch (code) {
- case MONO_PROFILE_START_LOAD:
- if (prof->module_start_load)
- prof->module_start_load (prof->profiler, module);
- break;
- case MONO_PROFILE_START_UNLOAD:
- if (prof->module_start_unload)
- prof->module_start_unload (prof->profiler, module);
- break;
- case MONO_PROFILE_END_UNLOAD:
- if (prof->module_end_unload)
- prof->module_end_unload (prof->profiler, module);
- break;
- default:
- g_assert_not_reached ();
- }
- }
-}
+ if (cil_code && cil_code >= start && cil_code < end) {
+ guint32 offset = cil_code - start;
-/**
- * mono_profiler_module_loaded:
- */
-void
-mono_profiler_module_loaded (MonoImage *module, int result)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_MODULE_EVENTS) && prof->module_end_load)
- prof->module_end_load (prof->profiler, module, result);
- }
-}
+ MonoProfilerCoverageData data = {
+ .method = method,
+ .il_offset = offset,
+ .counter = info->data [i].count,
+ .line = 1,
+ .column = 1,
+ };
-/**
- * mono_profiler_class_event:
- */
-void
-mono_profiler_class_event (MonoClass *klass, int code)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (!(prof->events & MONO_PROFILE_CLASS_EVENTS))
- continue;
-
- switch (code) {
- case MONO_PROFILE_START_LOAD:
- if (prof->class_start_load)
- prof->class_start_load (prof->profiler, klass);
- break;
- case MONO_PROFILE_START_UNLOAD:
- if (prof->class_start_unload)
- prof->class_start_unload (prof->profiler, klass);
- break;
- case MONO_PROFILE_END_UNLOAD:
- if (prof->class_end_unload)
- prof->class_end_unload (prof->profiler, klass);
- break;
- default:
- g_assert_not_reached ();
- }
- }
-}
+ if (minfo) {
+ MonoDebugSourceLocation *loc = mono_debug_method_lookup_location (minfo, offset);
-/**
- * mono_profiler_class_loaded:
- */
-void
-mono_profiler_class_loaded (MonoClass *klass, int result)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_CLASS_EVENTS) && prof->class_end_load)
- prof->class_end_load (prof->profiler, klass, result);
- }
-}
+ if (loc) {
+ data.file_name = g_strdup (loc->source_file);
+ data.line = loc->row;
+ data.column = loc->column;
-/**
- * mono_profiler_appdomain_event:
- */
-void
-mono_profiler_appdomain_event (MonoDomain *domain, int code)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (!(prof->events & MONO_PROFILE_APPDOMAIN_EVENTS))
- continue;
-
- switch (code) {
- case MONO_PROFILE_START_LOAD:
- if (prof->domain_start_load)
- prof->domain_start_load (prof->profiler, domain);
- break;
- case MONO_PROFILE_START_UNLOAD:
- if (prof->domain_start_unload)
- prof->domain_start_unload (prof->profiler, domain);
- break;
- case MONO_PROFILE_END_UNLOAD:
- if (prof->domain_end_unload)
- prof->domain_end_unload (prof->profiler, domain);
- break;
- default:
- g_assert_not_reached ();
+ mono_debug_free_source_location (loc);
+ }
+ }
+
+ cb (handle->prof, &data);
+
+ g_free ((char *) data.file_name);
}
}
-}
-/**
- * mono_profiler_appdomain_loaded:
- */
-void
-mono_profiler_appdomain_loaded (MonoDomain *domain, int result)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_APPDOMAIN_EVENTS) && prof->domain_end_load)
- prof->domain_end_load (prof->profiler, domain, result);
- }
+ mono_metadata_free_mh (header);
}
-void
-mono_profiler_appdomain_name (MonoDomain *domain, const char *name)
+MonoProfilerCoverageInfo *
+mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries)
{
- for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
- if ((prof->events & MONO_PROFILE_APPDOMAIN_EVENTS) && prof->domain_name)
- prof->domain_name (prof->profiler, domain, name);
-}
+ lazy_initialize_coverage ();
-void
-mono_profiler_context_loaded (MonoAppContext *context)
-{
- for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
- if ((prof->events & MONO_PROFILE_CONTEXT_EVENTS) && prof->context_load)
- prof->context_load (prof->profiler, context);
-}
+ gboolean cover = FALSE;
-void
-mono_profiler_context_unloaded (MonoAppContext *context)
-{
- for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
- if ((prof->events & MONO_PROFILE_CONTEXT_EVENTS) && prof->context_unload)
- prof->context_unload (prof->profiler, context);
-}
+ for (MonoProfilerHandle handle = mono_profiler_state.profilers; handle; handle = handle->next) {
+ MonoProfilerCoverageFilterCallback cb = handle->coverage_filter;
-/**
- * mono_profiler_shutdown:
- */
-void
-mono_profiler_shutdown (void)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (prof->shutdown_callback)
- prof->shutdown_callback (prof->profiler);
+ if (cb)
+ cover |= cb (handle->prof, method);
}
- mono_profiler_set_events ((MonoProfileFlags)0);
-}
+ if (!cover)
+ return NULL;
-/**
- * mono_profiler_gc_heap_resize:
- */
-void
-mono_profiler_gc_heap_resize (gint64 new_size)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_GC) && prof->gc_heap_resize)
- prof->gc_heap_resize (prof->profiler, new_size);
- }
-}
+ coverage_lock ();
-/**
- * mono_profiler_gc_event:
- */
-void
-mono_profiler_gc_event (MonoGCEvent event, int generation)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_GC) && prof->gc_event)
- prof->gc_event (prof->profiler, event, generation);
- }
-}
+ MonoProfilerCoverageInfo *info = g_malloc0 (sizeof (MonoProfilerCoverageInfo) + SIZEOF_VOID_P * 2 * entries);
-void
-mono_profiler_gc_moves (void **objects, int num)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_GC_MOVES) && prof->gc_moves)
- prof->gc_moves (prof->profiler, objects, num);
- }
-}
+ info->entries = entries;
-void
-mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj)
-{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_GC_ROOTS) && prof->gc_handle)
- prof->gc_handle (prof->profiler, op, type, handle, obj);
- }
+ g_hash_table_insert (mono_profiler_state.coverage_hash, method, info);
+
+ coverage_unlock ();
+
+ return info;
}
void
-mono_profiler_gc_roots (int num, void **objects, int *root_types, uintptr_t *extra_info)
+mono_profiler_coverage_free (MonoMethod *method)
{
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if ((prof->events & MONO_PROFILE_GC_ROOTS) && prof->gc_roots)
- prof->gc_roots (prof->profiler, num, objects, root_types, extra_info);
+ lazy_initialize_coverage ();
+
+ coverage_lock ();
+
+ MonoProfilerCoverageInfo *info = g_hash_table_lookup (mono_profiler_state.coverage_hash, method);
+
+ if (info) {
+ g_hash_table_remove (mono_profiler_state.coverage_hash, method);
+ g_free (info);
}
-}
-/**
- * mono_profiler_install_gc:
- */
-void
-mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback)
-{
- if (!prof_list)
- return;
- prof_list->gc_event = callback;
- prof_list->gc_heap_resize = heap_resize_callback;
+ coverage_unlock ();
}
-/**
- * mono_profiler_install_gc_moves:
- * \param callback callback function
- *
- * Install the \p callback function that the GC will call when moving objects.
- * The callback receives an array of pointers and the number of elements
- * in the array. Every even element in the array is the original object location
- * and the following odd element is the new location of the object in memory.
- * So the number of elements argument will always be a multiple of 2.
- * Since this callback happens during the GC, it is a restricted environment:
- * no locks can be taken and the object pointers can be inspected only once
- * the GC is finished (of course the original location pointers will not
- * point to valid objects anymore).
- */
-void
-mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback)
+mono_bool
+mono_profiler_enable_sampling (MonoProfilerHandle handle)
{
- if (!prof_list)
- return;
- prof_list->gc_moves = callback;
-}
+ if (mono_profiler_state.startup_done)
+ return FALSE;
-/**
- * mono_profiler_install_gc_roots:
- * \param handle_callback callback function
- * \param roots_callback callback function
- *
- * Install the \p handle_callback function that the GC will call when GC
- * handles are created or destroyed.
- * The callback receives an operation, which is either \c MONO_PROFILER_GC_HANDLE_CREATED
- * or \c MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the
- * object pointer, if present.
- * Install the \p roots_callback function that the GC will call when tracing
- * the roots for a collection.
- * The callback receives the number of elements and three arrays: an array
- * of objects, an array of root types and flags and an array of extra info.
- * The size of each array is given by the first argument.
- */
-void
-mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback, MonoProfileGCRootFunc roots_callback)
-{
- if (!prof_list)
- return;
- prof_list->gc_handle = handle_callback;
- prof_list->gc_roots = roots_callback;
-}
+ if (mono_profiler_state.sampling_owner)
+ return TRUE;
-void
-mono_profiler_gc_finalize_begin (void)
-{
- for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
- if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_begin)
- prof->gc_finalize_begin (prof->profiler);
-}
+ mono_profiler_state.sampling_owner = handle;
+ mono_profiler_state.sample_mode = MONO_PROFILER_SAMPLE_MODE_NONE;
+ mono_profiler_state.sample_freq = 100;
+ mono_os_sem_init (&mono_profiler_state.sampling_semaphore, 0);
-void
-mono_profiler_gc_finalize_object_begin (MonoObject *obj)
-{
- for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
- if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_begin)
- prof->gc_finalize_object_begin (prof->profiler, obj);
+ return TRUE;
}
-void
-mono_profiler_gc_finalize_object_end (MonoObject *obj)
+mono_bool
+mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint32_t freq)
{
- for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
- if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_end)
- prof->gc_finalize_object_end (prof->profiler, obj);
-}
+ if (handle != mono_profiler_state.sampling_owner)
+ return FALSE;
-void
-mono_profiler_gc_finalize_end (void)
-{
- for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
- if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_end)
- prof->gc_finalize_end (prof->profiler);
-}
+ mono_profiler_state.sample_mode = mode;
+ mono_profiler_state.sample_freq = freq;
-void
-mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end)
-{
- if (!prof_list)
- return;
+ mono_profiler_sampling_thread_post ();
- prof_list->gc_finalize_begin = begin;
- prof_list->gc_finalize_object_begin = begin_obj;
- prof_list->gc_finalize_object_end = end_obj;
- prof_list->gc_finalize_end = end;
+ return TRUE;
}
-void
-mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback)
+mono_bool
+mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq)
{
- if (!prof_list)
- return;
- prof_list->runtime_initialized_event = runtime_initialized_callback;
-}
+ if (mode)
+ *mode = mono_profiler_state.sample_mode;
-void
-mono_profiler_runtime_initialized (void) {
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (prof->runtime_initialized_event)
- prof->runtime_initialized_event (prof->profiler);
- }
-}
+ if (freq)
+ *freq = mono_profiler_state.sample_freq;
-void
-mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback) {
- if (!prof_list)
- return;
- prof_list->code_chunk_new = callback;
-}
-void
-mono_profiler_code_chunk_new (gpointer chunk, int size) {
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (prof->code_chunk_new)
- prof->code_chunk_new (prof->profiler, chunk, size);
- }
+ return handle == mono_profiler_state.sampling_owner;
}
-void
-mono_profiler_install_code_chunk_destroy (MonoProfilerCodeChunkDestroy callback) {
- if (!prof_list)
- return;
- prof_list->code_chunk_destroy = callback;
-}
-void
-mono_profiler_code_chunk_destroy (gpointer chunk) {
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (prof->code_chunk_destroy)
- prof->code_chunk_destroy (prof->profiler, chunk);
- }
-}
-
-void
-mono_profiler_install_code_buffer_new (MonoProfilerCodeBufferNew callback) {
- if (!prof_list)
- return;
- prof_list->code_buffer_new = callback;
+gboolean
+mono_profiler_sampling_enabled (void)
+{
+ return !!mono_profiler_state.sampling_owner;
}
void
-mono_profiler_install_iomap (MonoProfileIomapFunc callback)
+mono_profiler_sampling_thread_post (void)
{
- if (!prof_list)
- return;
- prof_list->iomap_cb = callback;
+ mono_os_sem_post (&mono_profiler_state.sampling_semaphore);
}
void
-mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, gconstpointer data) {
- ProfilerDesc *prof;
- for (prof = prof_list; prof; prof = prof->next) {
- if (prof->code_buffer_new)
- prof->code_buffer_new (prof->profiler, buffer, size, type, (void*)data);
- }
+mono_profiler_sampling_thread_wait (void)
+{
+ mono_os_sem_wait (&mono_profiler_state.sampling_semaphore, MONO_SEM_FLAGS_NONE);
}
-static GHashTable *coverage_hash = NULL;
-
-MonoProfileCoverageInfo*
-mono_profiler_coverage_alloc (MonoMethod *method, int entries)
+mono_bool
+mono_profiler_enable_allocations (void)
{
- MonoProfileCoverageInfo *res;
- int instrument = FALSE;
- ProfilerDesc *prof;
-
- for (prof = prof_list; prof; prof = prof->next) {
- /* note that we call the filter on all the profilers even if just
- * a single one would be enough to instrument a method
- */
- if (prof->coverage_filter_cb)
- if (prof->coverage_filter_cb (prof->profiler, method))
- instrument = TRUE;
- }
- if (!instrument)
- return NULL;
-
- mono_profiler_coverage_lock ();
- if (!coverage_hash)
- coverage_hash = g_hash_table_new (NULL, NULL);
-
- res = (MonoProfileCoverageInfo *)g_malloc0 (sizeof (MonoProfileCoverageInfo) + sizeof (void*) * 2 * entries);
-
- res->entries = entries;
+ if (mono_profiler_state.startup_done)
+ return FALSE;
- g_hash_table_insert (coverage_hash, method, res);
- mono_profiler_coverage_unlock ();
+ mono_profiler_state.allocations = TRUE;
- return res;
+ return TRUE;
}
-/* safe only when the method antive code has been unloaded */
void
-mono_profiler_coverage_free (MonoMethod *method)
+mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb)
{
- MonoProfileCoverageInfo* info;
-
- mono_profiler_coverage_lock ();
- if (!coverage_hash) {
- mono_profiler_coverage_unlock ();
- return;
- }
-
- info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method);
- if (info) {
- g_free (info);
- g_hash_table_remove (coverage_hash, method);
- }
- mono_profiler_coverage_unlock ();
+ InterlockedWritePointer (&handle->call_instrumentation_filter, (gpointer) cb);
}
-/**
- * mono_profiler_coverage_get:
- * \param prof The profiler handle, installed with mono_profiler_install
- * \param method the method to gather information from.
- * \param func A routine that will be called back with the results
- *
- * If the \c MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation
- * it is possible to obtain coverage information about a give method.
- *
- * The function \p func will be invoked repeatedly with instances of the
- * \c MonoProfileCoverageEntry structure.
- */
-void
-mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func)
+gboolean
+mono_profiler_should_instrument_method (MonoMethod *method, gboolean entry)
{
- MonoError error;
- MonoProfileCoverageInfo* info = NULL;
- int i, offset;
- guint32 code_size;
- const unsigned char *start, *end, *cil_code;
- MonoMethodHeader *header;
- MonoProfileCoverageEntry entry;
- MonoDebugMethodInfo *debug_minfo;
-
- mono_profiler_coverage_lock ();
- if (coverage_hash)
- info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method);
- mono_profiler_coverage_unlock ();
-
- if (!info)
- return;
-
- header = mono_method_get_header_checked (method, &error);
- mono_error_assert_ok (&error);
- start = mono_method_header_get_code (header, &code_size, NULL);
- debug_minfo = mono_debug_lookup_method (method);
+ MonoProfilerCallInstrumentationFlags flags = MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
- end = start + code_size;
- for (i = 0; i < info->entries; ++i) {
- cil_code = info->data [i].cil_code;
- if (cil_code && cil_code >= start && cil_code < end) {
- char *fname = NULL;
- offset = cil_code - start;
- entry.iloffset = offset;
- entry.method = method;
- entry.counter = info->data [i].count;
- entry.line = entry.col = 1;
- entry.filename = NULL;
- if (debug_minfo) {
- MonoDebugSourceLocation *location;
-
- location = mono_debug_method_lookup_location (debug_minfo, offset);
- if (location) {
- entry.line = location->row;
- entry.col = location->column;
- entry.filename = fname = g_strdup (location->source_file);
- mono_debug_free_source_location (location);
- }
- }
+ for (MonoProfilerHandle handle = mono_profiler_state.profilers; handle; handle = handle->next) {
+ MonoProfilerCallInstrumentationFilterCallback cb = handle->call_instrumentation_filter;
- func (prof, &entry);
- g_free (fname);
- }
+ if (cb)
+ flags |= cb (handle->prof, method);
}
- mono_metadata_free_mh (header);
-}
-
-typedef void (*ProfilerInitializer) (const char*);
-#define INITIALIZER_NAME "mono_profiler_startup"
-
-
-static gboolean
-load_profiler (MonoDl *pmodule, const char *desc, const char *symbol)
-{
- char *err;
- ProfilerInitializer func;
- if (!pmodule)
- return FALSE;
-
- if ((err = mono_dl_symbol (pmodule, symbol, (gpointer *) &func))) {
- g_free (err);
- return FALSE;
- } else {
- func (desc);
- }
- return TRUE;
+ if (entry)
+ return flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE;
+ else
+ return flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
}
-static gboolean
-load_embedded_profiler (const char *desc, const char *name)
+void
+mono_profiler_started (void)
{
- char *err = NULL;
- char *symbol;
- MonoDl *pmodule = NULL;
- gboolean result;
-
- /*
- * Some profilers (such as ours) may need to call back into the runtime
- * from their sampling callback (which is called in async-signal context).
- * They need to be able to know that all references back to the runtime
- * have been resolved; otherwise, calling runtime functions may result in
- * invoking the dynamic linker which is not async-signal-safe. Passing
- * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront.
- */
- pmodule = mono_dl_open (NULL, MONO_DL_EAGER, &err);
- if (!pmodule) {
- g_warning ("Could not open main executable (%s)", err);
- g_free (err);
- return FALSE;
- }
-
- symbol = g_strdup_printf (INITIALIZER_NAME "_%s", name);
- result = load_profiler (pmodule, desc, symbol);
- g_free (symbol);
-
- return result;
+ mono_profiler_state.startup_done = TRUE;
}
-// TODO: Much of the library loading code here is custom. It would be better to merge this with mono-dl
-static gboolean
-load_profiler_from_directory (const char *directory, const char *libname, const char *desc)
+void
+mono_profiler_cleanup (void)
{
- MonoDl *pmodule = NULL;
- char* path;
- char *err;
- void *iter;
-
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler %s from %s (desc %s)", libname, directory, desc);
-
- iter = NULL;
- err = NULL;
- while ((path = mono_dl_build_path (directory, libname, &iter))) {
- pmodule = mono_dl_open (path, MONO_DL_EAGER, &err);
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler: %s, %ssuccessful, err: %s", path, pmodule?"":"not ", err);
- g_free (path);
- g_free (err);
- if (pmodule)
- return load_profiler (pmodule, desc, INITIALIZER_NAME);
+ for (MonoProfilerHandle handle = mono_profiler_state.profilers; handle; handle = handle->next) {
+#define _MONO_PROFILER_EVENT(name) \
+ mono_profiler_set_ ## name ## _callback (handle, NULL); \
+ g_assert (!handle->name ## _cb);
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
}
-
- return FALSE;
-}
-static gboolean
-load_profiler_from_mono_installation (const char *libname, const char *desc)
-{
- char *err = NULL;
- MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_EAGER, &err);
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler from runtime libs: %s, %ssuccessful, err: %s", libname, pmodule?"":"not ", err);
- g_free (err);
- if (pmodule)
- return load_profiler (pmodule, desc, INITIALIZER_NAME);
- return FALSE;
+#define _MONO_PROFILER_EVENT(name, type) \
+ g_assert (!mono_profiler_state.name ## _count);
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
}
-/**
- * mono_profiler_load:
- * \param desc arguments to configure the profiler
- *
- * Invoke this method to initialize the profiler. This will drive the
- * loading of the internal ("default") or any external profilers.
- *
- * This routine is invoked by Mono's driver, but must be called manually
- * if you embed Mono into your application.
- */
-void
-mono_profiler_load (const char *desc)
+static void
+update_callback (volatile gpointer *location, gpointer new_, volatile gint32 *counter)
{
- char *cdesc = NULL;
- mono_gc_base_init ();
+ gpointer old;
- if (!desc || (strcmp ("default", desc) == 0)) {
- desc = "log:report";
- }
- /* we keep command-line compat with the old version here */
- if (strncmp (desc, "default:", 8) == 0) {
- gchar **args, **ptr;
- GString *str = g_string_new ("log:report");
- args = g_strsplit (desc + 8, ",", -1);
- for (ptr = args; ptr && *ptr; ptr++) {
- const char *arg = *ptr;
-
- if (!strcmp (arg, "time"))
- g_string_append (str, ",calls");
- else if (!strcmp (arg, "alloc"))
- g_string_append (str, ",alloc");
- else if (!strcmp (arg, "stat"))
- g_string_append (str, ",sample");
- else if (!strcmp (arg, "jit"))
- continue; /* accept and do nothing */
- else if (strncmp (arg, "file=", 5) == 0) {
- g_string_append_printf (str, ",output=%s", arg + 5);
- } else {
- fprintf (stderr, "profiler : Unknown argument '%s'.\n", arg);
- return;
- }
- }
- desc = cdesc = g_string_free (str, FALSE);
- }
- {
- const char* col = strchr (desc, ':');
- char* libname;
- char *mname;
- gboolean res = FALSE;
-
- if (col != NULL) {
- mname = (char *)g_memdup (desc, col - desc + 1);
- mname [col - desc] = 0;
- } else {
- mname = g_strdup (desc);
- }
- if (!load_embedded_profiler (desc, mname)) {
- libname = g_strdup_printf ("mono-profiler-%s", mname);
- res = load_profiler_from_mono_installation (libname, desc);
- if (!res && mono_config_get_assemblies_dir ())
- res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, desc);
- if (!res)
- 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);
- g_free (libname);
- }
- g_free (mname);
- }
- g_free (cdesc);
-}
+ do {
+ old = InterlockedReadPointer (location);
+ } while (InterlockedCompareExchangePointer (location, new_, old) != old);
+
+ /*
+ * At this point, we could have installed a NULL callback while the counter
+ * is still non-zero, i.e. setting the callback and modifying the counter
+ * is not a single atomic operation. This is fine as we make sure callbacks
+ * are non-NULL before invoking them (see the code below that generates the
+ * raise functions), and besides, updating callbacks at runtime is an
+ * inherently racy operation.
+ */
+ if (old)
+ InterlockedDecrement (counter);
+
+ if (new_)
+ InterlockedIncrement (counter);
+}
+
+#define _MONO_PROFILER_EVENT(name, type) \
+ void \
+ mono_profiler_set_ ## name ## _callback (MonoProfilerHandle handle, MonoProfiler ## type ## Callback cb) \
+ { \
+ update_callback (&handle->name ## _cb, (gpointer) cb, &mono_profiler_state.name ## _count); \
+ }
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+
+#define _MONO_PROFILER_EVENT(name, type, params, args) \
+ void \
+ mono_profiler_raise_ ## name params \
+ { \
+ for (MonoProfilerHandle h = mono_profiler_state.profilers; h; h = h->next) { \
+ MonoProfiler ## type ## Callback cb = h->name ## _cb; \
+ if (cb) \
+ cb args; \
+ } \
+ }
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name, type, (void), (h->prof))
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name), (h->prof, arg1_name))
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name, arg2_type arg2_name), (h->prof, arg1_name, arg2_name))
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name), (h->prof, arg1_name, arg2_name, arg3_name))
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name), (h->prof, arg1_name, arg2_name, arg3_name, arg4_name))
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
-/**
- * \file
+/*
+ * 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.
*/
#ifndef __MONO_PROFILER_H__
#define __MONO_PROFILER_H__
-#include <mono/metadata/object.h>
#include <mono/metadata/appdomain.h>
+#include <mono/metadata/mono-gc.h>
+#include <mono/metadata/object.h>
MONO_BEGIN_DECLS
-#define MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH 128
-
-typedef enum {
- MONO_PROFILE_NONE = 0,
- MONO_PROFILE_APPDOMAIN_EVENTS = 1 << 0,
- MONO_PROFILE_ASSEMBLY_EVENTS = 1 << 1,
- MONO_PROFILE_MODULE_EVENTS = 1 << 2,
- MONO_PROFILE_CLASS_EVENTS = 1 << 3,
- MONO_PROFILE_JIT_COMPILATION = 1 << 4,
- MONO_PROFILE_INLINING = 1 << 5,
- MONO_PROFILE_EXCEPTIONS = 1 << 6,
- MONO_PROFILE_ALLOCATIONS = 1 << 7,
- MONO_PROFILE_GC = 1 << 8,
- MONO_PROFILE_THREADS = 1 << 9,
- MONO_PROFILE_REMOTING = 1 << 10,
- MONO_PROFILE_TRANSITIONS = 1 << 11,
- MONO_PROFILE_ENTER_LEAVE = 1 << 12,
- MONO_PROFILE_COVERAGE = 1 << 13,
- MONO_PROFILE_INS_COVERAGE = 1 << 14,
- MONO_PROFILE_STATISTICAL = 1 << 15,
- MONO_PROFILE_METHOD_EVENTS = 1 << 16,
- MONO_PROFILE_MONITOR_EVENTS = 1 << 17,
- MONO_PROFILE_IOMAP_EVENTS = 1 << 18, /* this should likely be removed, too */
- MONO_PROFILE_GC_MOVES = 1 << 19,
- MONO_PROFILE_GC_ROOTS = 1 << 20,
- MONO_PROFILE_CONTEXT_EVENTS = 1 << 21,
- MONO_PROFILE_GC_FINALIZATION = 1 << 22
-} MonoProfileFlags;
-
-typedef enum {
- MONO_PROFILE_OK,
- MONO_PROFILE_FAILED
-} MonoProfileResult;
+/*
+ * This value will be incremented whenever breaking changes to the profiler API
+ * are made. This macro is intended for use in profiler modules that wish to
+ * support older versions of the profiler API.
+ */
+#define MONO_PROFILER_API_VERSION 2
-// Keep somewhat in sync with libgc/include/gc.h:enum GC_EventType
-typedef enum {
- MONO_GC_EVENT_START,
- MONO_GC_EVENT_MARK_START,
- MONO_GC_EVENT_MARK_END,
- MONO_GC_EVENT_RECLAIM_START,
- MONO_GC_EVENT_RECLAIM_END,
- MONO_GC_EVENT_END,
- /*
- * This is the actual arrival order of the following events:
- *
- * MONO_GC_EVENT_PRE_STOP_WORLD
- * MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED
- * MONO_GC_EVENT_POST_STOP_WORLD
- * MONO_GC_EVENT_PRE_START_WORLD
- * MONO_GC_EVENT_POST_START_WORLD_UNLOCKED
- * MONO_GC_EVENT_POST_START_WORLD
- *
- * The LOCKED and UNLOCKED events guarantee that, by the time they arrive,
- * the GC and suspend locks will both have been acquired and released,
- * respectively.
- */
- MONO_GC_EVENT_PRE_STOP_WORLD,
- MONO_GC_EVENT_POST_STOP_WORLD,
- MONO_GC_EVENT_PRE_START_WORLD,
- MONO_GC_EVENT_POST_START_WORLD,
- MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED,
- MONO_GC_EVENT_POST_START_WORLD_UNLOCKED
-} MonoGCEvent;
-
-/* coverage info */
-typedef struct {
- MonoMethod *method;
- int iloffset;
- int counter;
- const char *filename;
- int line;
- int col;
-} MonoProfileCoverageEntry;
-
-/* executable code buffer info */
-typedef enum {
- MONO_PROFILER_CODE_BUFFER_UNKNOWN,
- MONO_PROFILER_CODE_BUFFER_METHOD,
- MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE,
- MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE,
- MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE,
- MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE,
- MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE,
- MONO_PROFILER_CODE_BUFFER_HELPER,
- MONO_PROFILER_CODE_BUFFER_MONITOR,
- MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE,
- MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING,
- MONO_PROFILER_CODE_BUFFER_LAST
-} MonoProfilerCodeBufferType;
+/*
+ * Loads a profiler module based on the specified description. The description
+ * can be of the form "name:args" or just "name". For example, "log:sample" and
+ * "log" will both load "libmono-profiler-log.so". The description is passed to
+ * the module after it has been loaded. If the specified module has already
+ * been loaded, this function has no effect.
+ *
+ * A module called foo should declare an entry point like so:
+ *
+ * void mono_profiler_init_foo (const char *desc)
+ * {
+ * }
+ *
+ * This function is not async safe.
+ */
+MONO_API void mono_profiler_load (const char *desc);
typedef struct _MonoProfiler MonoProfiler;
+typedef struct _MonoProfilerDesc *MonoProfilerHandle;
-typedef enum {
- MONO_PROFILER_MONITOR_CONTENTION = 1,
- MONO_PROFILER_MONITOR_DONE = 2,
- MONO_PROFILER_MONITOR_FAIL = 3
-} MonoProfilerMonitorEvent;
+/*
+ * Installs a profiler and returns a handle for it. The handle is used with the
+ * other functions in the profiler API (e.g. for setting up callbacks).
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * Example usage:
+ *
+ * struct _MonoProfiler {
+ * int my_stuff;
+ * // ...
+ * };
+ *
+ * MonoProfiler *prof = calloc (1, sizeof (MonoProfiler));
+ * MonoProfilerHandle handle = mono_profiler_install (prof);
+ * mono_profiler_set_shutdown_callback (handle, my_shutdown_cb);
+ *
+ * This function is not async safe.
+ */
+MONO_API MonoProfilerHandle mono_profiler_install (MonoProfiler *prof);
-typedef enum {
- MONO_PROFILER_CALL_CHAIN_NONE = 0,
- MONO_PROFILER_CALL_CHAIN_NATIVE = 1,
- MONO_PROFILER_CALL_CHAIN_GLIBC = 2,
- MONO_PROFILER_CALL_CHAIN_MANAGED = 3,
- MONO_PROFILER_CALL_CHAIN_INVALID = 4
-} MonoProfilerCallChainStrategy;
+typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, MonoMethod *method);
-typedef enum {
- MONO_PROFILER_GC_HANDLE_CREATED,
- MONO_PROFILER_GC_HANDLE_DESTROYED
-} MonoProfileGCHandleEvent;
+/*
+ * Sets a code coverage filter function. The profiler API will invoke filter
+ * functions from all installed profilers. If any of them return TRUE, then the
+ * given method will be instrumented for coverage analysis. All filters are
+ * guaranteed to be called exactly once per method, even if an earlier filter
+ * has already returned TRUE.
+ *
+ * Note that filter functions must be installed before a method is compiled in
+ * order to have any effect, i.e. you should register your filter function in
+ * your profiler's init function.
+ *
+ * This function is async safe.
+ */
+MONO_API void mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb);
-typedef enum {
- MONO_PROFILE_GC_ROOT_PINNING = 1 << 8,
- MONO_PROFILE_GC_ROOT_WEAKREF = 2 << 8,
- MONO_PROFILE_GC_ROOT_INTERIOR = 4 << 8,
- /* the above are flags, the type is in the low 2 bytes */
- MONO_PROFILE_GC_ROOT_STACK = 0,
- MONO_PROFILE_GC_ROOT_FINALIZER = 1,
- MONO_PROFILE_GC_ROOT_HANDLE = 2,
- MONO_PROFILE_GC_ROOT_OTHER = 3,
- MONO_PROFILE_GC_ROOT_MISC = 4, /* could be stack, handle, etc. */
- MONO_PROFILE_GC_ROOT_TYPEMASK = 0xff
-} MonoProfileGCRootType;
+typedef struct {
+ MonoMethod *method;
+ uint32_t il_offset;
+ uint32_t counter;
+ const char *file_name;
+ uint32_t line;
+ uint32_t column;
+} MonoProfilerCoverageData;
+
+typedef void (*MonoProfilerCoverageCallback) (MonoProfiler *prof, const MonoProfilerCoverageData *data);
/*
- * Functions that the runtime will call on the profiler.
+ * Retrieves all coverage data for the specified method and invokes the given
+ * callback for each entry.
+ *
+ * This function is not async safe.
*/
+MONO_API void mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
-typedef void (*MonoProfileFunc) (MonoProfiler *prof);
+typedef enum {
+ /*
+ * Do not perform sampling. Will make the sampling thread sleep until the
+ * sampling mode is changed to one of the below modes.
+ */
+ MONO_PROFILER_SAMPLE_MODE_NONE = 0,
+ /*
+ * Try to base sampling frequency on process activity. Falls back to
+ * MONO_PROFILER_SAMPLE_MODE_REAL if such a clock is not available.
+ */
+ MONO_PROFILER_SAMPLE_MODE_PROCESS = 1,
+ /*
+ * Base sampling frequency on wall clock time. Uses a monotonic clock when
+ * available (all major platforms).
+ */
+ MONO_PROFILER_SAMPLE_MODE_REAL = 2,
+} MonoProfilerSampleMode;
-typedef void (*MonoProfileAppDomainFunc) (MonoProfiler *prof, MonoDomain *domain);
-typedef void (*MonoProfileContextFunc) (MonoProfiler *prof, MonoAppContext *context);
-typedef void (*MonoProfileMethodFunc) (MonoProfiler *prof, MonoMethod *method);
-typedef void (*MonoProfileClassFunc) (MonoProfiler *prof, MonoClass *klass);
-typedef void (*MonoProfileModuleFunc) (MonoProfiler *prof, MonoImage *module);
-typedef void (*MonoProfileAssemblyFunc) (MonoProfiler *prof, MonoAssembly *assembly);
-typedef void (*MonoProfileMonitorFunc) (MonoProfiler *prof, MonoObject *obj, MonoProfilerMonitorEvent event);
+/*
+ * Enables the sampling thread. You must call this function if you intend to use
+ * statistical sampling; mono_profiler_set_sample_mode will have no effect if
+ * this function has not been called. The first profiler to call this function
+ * will get ownership over sampling settings (mode and frequency) so that no
+ * other profiler can change those settings. Returns TRUE if the sampling
+ * thread was enabled, or FALSE if the function was called too late for this
+ * to be possible.
+ *
+ * Note that you still need to call mono_profiler_set_sample_mode with a mode
+ * other than MONO_PROFILER_SAMPLE_MODE_NONE to actually start sampling.
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * This function is not async safe.
+ */
+MONO_API mono_bool mono_profiler_enable_sampling (MonoProfilerHandle handle);
-typedef void (*MonoProfileExceptionFunc) (MonoProfiler *prof, MonoObject *object);
-typedef void (*MonoProfileExceptionClauseFunc) (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num);
-typedef void (*MonoProfileExceptionClauseFunc2) (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num, MonoObject *exc);
+/*
+ * 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, uint32_t freq);
-typedef void (*MonoProfileAppDomainResult)(MonoProfiler *prof, MonoDomain *domain, int result);
-typedef void (*MonoProfileAppDomainFriendlyNameFunc) (MonoProfiler *prof, MonoDomain *domain, const char *name);
-typedef void (*MonoProfileMethodResult) (MonoProfiler *prof, MonoMethod *method, int result);
-typedef void (*MonoProfileJitResult) (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result);
-typedef void (*MonoProfileClassResult) (MonoProfiler *prof, MonoClass *klass, int result);
-typedef void (*MonoProfileModuleResult) (MonoProfiler *prof, MonoImage *module, int result);
-typedef void (*MonoProfileAssemblyResult) (MonoProfiler *prof, MonoAssembly *assembly, int result);
+/*
+ * Retrieves the current sampling mode and/or frequency (in Hz). Returns TRUE if
+ * the calling profiler is allowed to change the sampling settings; otherwise,
+ * FALSE.
+ *
+ * This function is async safe.
+ */
+MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq);
-typedef void (*MonoProfileMethodInline) (MonoProfiler *prof, MonoMethod *parent, MonoMethod *child, int *ok);
+/*
+ * Enables instrumentation of GC allocations. This is necessary so that managed
+ * allocators can be instrumented with a call into the profiler API. Allocations
+ * will not be reported unless this function is called. Returns TRUE if
+ * allocation instrumentation was enabled, or FALSE if the function was called
+ * too late for this to be possible.
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * This function is not async safe.
+ */
+MONO_API mono_bool mono_profiler_enable_allocations (void);
-typedef void (*MonoProfileThreadFunc) (MonoProfiler *prof, uintptr_t tid);
-typedef void (*MonoProfileThreadNameFunc) (MonoProfiler *prof, uintptr_t tid, const char *name);
-typedef void (*MonoProfileAllocFunc) (MonoProfiler *prof, MonoObject *obj, MonoClass *klass);
-typedef void (*MonoProfileStatFunc) (MonoProfiler *prof, mono_byte *ip, void *context);
-typedef void (*MonoProfileStatCallChainFunc) (MonoProfiler *prof, int call_chain_depth, mono_byte **ip, void *context);
-typedef void (*MonoProfileGCFunc) (MonoProfiler *prof, MonoGCEvent event, int generation);
-typedef void (*MonoProfileGCMoveFunc) (MonoProfiler *prof, void **objects, int num);
-typedef void (*MonoProfileGCResizeFunc) (MonoProfiler *prof, int64_t new_size);
-typedef void (*MonoProfileGCHandleFunc) (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj);
-typedef void (*MonoProfileGCRootFunc) (MonoProfiler *prof, int num_roots, void **objects, int *root_types, uintptr_t *extra_info);
+typedef enum {
+ /* Do not instrument calls. */
+ MONO_PROFILER_CALL_INSTRUMENTATION_NONE = 1 << 0,
+ /* Instrument method prologues. */
+ MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE = 1 << 1,
+ /* Instrument method epilogues. */
+ MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE = 1 << 2,
+} MonoProfilerCallInstrumentationFlags;
-typedef void (*MonoProfileGCFinalizeFunc) (MonoProfiler *prof);
-typedef void (*MonoProfileGCFinalizeObjectFunc) (MonoProfiler *prof, MonoObject *obj);
+typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFilterCallback) (MonoProfiler *prof, MonoMethod *method);
-typedef void (*MonoProfileIomapFunc) (MonoProfiler *prof, const char *report, const char *pathname, const char *new_pathname);
+/*
+ * Sets a call instrumentation filter function. The profiler API will invoke
+ * filter functions from all installed profilers. If any of them return flags
+ * other than MONO_PROFILER_CALL_INSTRUMENTATION_NONE, then the given method
+ * will be instrumented as requested. All filters are guaranteed to be called
+ * at least once (possibly more) per method entry and exit, even if earlier
+ * filters have already specified all flags.
+ *
+ * Note that filter functions must be installed before a method is compiled in
+ * order to have any effect, i.e. you should register your filter function in
+ * your profiler's init function.
+ *
+ * Keep in mind that method instrumentation is extremely heavy and will slow
+ * down most applications to a crawl. Consider using sampling instead if it
+ * would work for your use case.
+ *
+ * This function is async safe.
+ */
+MONO_API void mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb);
-typedef mono_bool (*MonoProfileCoverageFilterFunc) (MonoProfiler *prof, MonoMethod *method);
+#ifdef MONO_PROFILER_UNSTABLE_GC_ROOTS
+typedef enum {
+ /* Upper 2 bytes. */
+ MONO_PROFILER_GC_ROOT_PINNING = 1 << 8,
+ MONO_PROFILER_GC_ROOT_WEAKREF = 2 << 8,
+ MONO_PROFILER_GC_ROOT_INTERIOR = 4 << 8,
+
+ /* Lower 2 bytes (flags). */
+ MONO_PROFILER_GC_ROOT_STACK = 1 << 0,
+ MONO_PROFILER_GC_ROOT_FINALIZER = 1 << 1,
+ MONO_PROFILER_GC_ROOT_HANDLE = 1 << 2,
+ MONO_PROFILER_GC_ROOT_OTHER = 1 << 3,
+ MONO_PROFILER_GC_ROOT_MISC = 1 << 4,
+
+ MONO_PROFILER_GC_ROOT_TYPEMASK = 0xff,
+} MonoProfilerGCRootType;
+#endif
-typedef void (*MonoProfileCoverageFunc) (MonoProfiler *prof, const MonoProfileCoverageEntry *entry);
+typedef enum {
+ /* data = MonoMethod *method */
+ MONO_PROFILER_CODE_BUFFER_METHOD = 0,
+ MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE = 1,
+ MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE = 2,
+ MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE = 3,
+ MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE = 4,
+ /* data = const char *name */
+ MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE = 5,
+ MONO_PROFILER_CODE_BUFFER_HELPER = 6,
+ MONO_PROFILER_CODE_BUFFER_MONITOR = 7,
+ MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE = 8,
+ MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING = 9,
+} MonoProfilerCodeBufferType;
-typedef void (*MonoProfilerCodeChunkNew) (MonoProfiler *prof, void* chunk, int size);
-typedef void (*MonoProfilerCodeChunkDestroy) (MonoProfiler *prof, void* chunk);
-typedef void (*MonoProfilerCodeBufferNew) (MonoProfiler *prof, void* buffer, int size, MonoProfilerCodeBufferType type, void *data);
+typedef enum {
+ 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,
+ MONO_GC_EVENT_POST_START_WORLD = 9,
+} MonoProfilerGCEvent;
/*
- * Function the profiler may call.
+ * The macros below will generate the majority of the callback API. Refer to
+ * mono/metadata/profiler-events.h for a list of callbacks. They are expanded
+ * like so:
+ *
+ * typedef void (*MonoProfilerRuntimeInitializedCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_runtime_initialized_callback (MonoProfiler *prof, MonoProfilerRuntimeInitializedCallback cb);
+ *
+ * typedef void (*MonoProfilerRuntimeShutdownCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_runtime_shutdown_callback (MonoProfiler *prof, MonoProfilerRuntimeShutdownCallback cb);
+ *
+ * typedef void (*MonoProfilerContextLoadedCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_context_loaded_callback (MonoProfiler *prof, MonoProfilerContextLoadedCallback cb);
+ *
+ * typedef void (*MonoProfilerContextUnloadedCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_context_unloaded_callback (MonoProfiler *prof, MonoProfilerContextUnloadedCallback cb);
+ *
+ * Etc.
+ *
+ * To remove a callback, pass NULL instead of a valid function pointer.
+ * Callbacks can be changed at any point, but note that doing so is inherently
+ * racy with respect to threads that aren't suspended, i.e. you may still see a
+ * call from another thread right after you change a callback.
+ *
+ * These functions are async safe.
*/
-MONO_API void mono_profiler_install (MonoProfiler *prof, MonoProfileFunc shutdown_callback);
-MONO_API void mono_profiler_set_events (MonoProfileFlags events);
-
-MONO_API MonoProfileFlags mono_profiler_get_events (void);
-
-MONO_API void mono_profiler_install_appdomain (MonoProfileAppDomainFunc start_load, MonoProfileAppDomainResult end_load,
- MonoProfileAppDomainFunc start_unload, MonoProfileAppDomainFunc end_unload);
-MONO_API void mono_profiler_install_appdomain_name (MonoProfileAppDomainFriendlyNameFunc domain_name_cb);
-MONO_API void mono_profiler_install_context (MonoProfileContextFunc load, MonoProfileContextFunc unload);
-MONO_API void mono_profiler_install_assembly (MonoProfileAssemblyFunc start_load, MonoProfileAssemblyResult end_load,
- MonoProfileAssemblyFunc start_unload, MonoProfileAssemblyFunc end_unload);
-MONO_API void mono_profiler_install_module (MonoProfileModuleFunc start_load, MonoProfileModuleResult end_load,
- MonoProfileModuleFunc start_unload, MonoProfileModuleFunc end_unload);
-MONO_API void mono_profiler_install_class (MonoProfileClassFunc start_load, MonoProfileClassResult end_load,
- MonoProfileClassFunc start_unload, MonoProfileClassFunc end_unload);
-
-MONO_API void mono_profiler_install_jit_compile (MonoProfileMethodFunc start, MonoProfileMethodResult end);
-MONO_API void mono_profiler_install_jit_end (MonoProfileJitResult end);
-MONO_API void mono_profiler_install_method_free (MonoProfileMethodFunc callback);
-MONO_API void mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end);
-MONO_API void mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave);
-MONO_API void mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end);
-MONO_API void mono_profiler_install_thread_name (MonoProfileThreadNameFunc thread_name_cb);
-MONO_API void mono_profiler_install_transition (MonoProfileMethodResult callback);
-MONO_API void mono_profiler_install_allocation (MonoProfileAllocFunc callback);
-MONO_API void mono_profiler_install_monitor (MonoProfileMonitorFunc callback);
-MONO_API void mono_profiler_install_statistical (MonoProfileStatFunc callback);
-MONO_API void mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy);
-MONO_API void mono_profiler_install_exception (MonoProfileExceptionFunc throw_callback, MonoProfileMethodFunc exc_method_leave, MonoProfileExceptionClauseFunc clause_callback);
-MONO_API void mono_profiler_install_exception_clause (MonoProfileExceptionClauseFunc2 clause_callback);
-MONO_API void mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback);
-MONO_API void mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func);
-MONO_API void mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback);
-MONO_API void mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback);
-MONO_API void mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback, MonoProfileGCRootFunc roots_callback);
-MONO_API void mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end);
-MONO_API void mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback);
-
-MONO_API void mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback);
-MONO_API void mono_profiler_install_code_chunk_destroy (MonoProfilerCodeChunkDestroy callback);
-MONO_API void mono_profiler_install_code_buffer_new (MonoProfilerCodeBufferNew callback);
-
-MONO_API void mono_profiler_install_iomap (MonoProfileIomapFunc callback);
-
-MONO_API void mono_profiler_load (const char *desc);
-typedef enum {
- /* Elapsed time is tracked by user+kernel time of the process - this is the default*/
- MONO_PROFILER_STAT_MODE_PROCESS = 0,
- /* Elapsed time is tracked by wallclock time */
- MONO_PROFILER_STAT_MODE_REAL = 1,
-} MonoProfileSamplingMode;
-
-MONO_API void mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_hz);
+#define _MONO_PROFILER_EVENT(type, ...) \
+ typedef void (*MonoProfiler ## type ## Callback) (__VA_ARGS__);
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(type, MonoProfiler *prof)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+
+#define _MONO_PROFILER_EVENT(name, type) \
+ MONO_API void mono_profiler_set_ ## name ## _callback (MonoProfilerHandle handle, MonoProfiler ## type ## Callback cb);
+#define MONO_PROFILER_EVENT_0(name, type) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+ _MONO_PROFILER_EVENT(name, type)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
MONO_END_DECLS
-#endif /* __MONO_PROFILER_H__ */
-
+#endif // __MONO_PROFILER_H__
SGEN_LOG (9, "Array instance %p: size: %lu, rank: %d, length: %lu", array, (unsigned long)objsize, vt->rank, (unsigned long)mono_array_length (array));
}
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
+ if (MONO_PROFILER_ENABLED (gc_moves))
mono_sgen_register_moved_object (obj, destination);
}
{
MONO_GC_BEGIN (generation);
- mono_profiler_gc_event (MONO_GC_EVENT_START, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_START, generation));
#ifndef DISABLE_PERFCOUNTERS
if (generation == GENERATION_NURSERY)
{
MONO_GC_END (generation);
- mono_profiler_gc_event (MONO_GC_EVENT_END, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_END, generation));
}
static void G_GNUC_UNUSED
static void G_GNUC_UNUSED
sgen_client_binary_protocol_mark_start (int generation)
{
- mono_profiler_gc_event (MONO_GC_EVENT_MARK_START, generation);
}
static void G_GNUC_UNUSED
sgen_client_binary_protocol_mark_end (int generation)
{
- mono_profiler_gc_event (MONO_GC_EVENT_MARK_END, generation);
}
static void G_GNUC_UNUSED
sgen_client_binary_protocol_reclaim_start (int generation)
{
- mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_START, generation);
}
static void G_GNUC_UNUSED
sgen_client_binary_protocol_reclaim_end (int generation)
{
- mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_END, generation);
}
static void
{
MonoObject *obj = sgen_alloc_obj (vtable, size);
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) {
- if (obj)
- mono_profiler_allocation (obj);
- }
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()) && obj)
+ MONO_PROFILER_RAISE (gc_allocation, (obj));
return obj;
}
{
MonoObject *obj = sgen_alloc_obj_pinned (vtable, size);
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) {
- if (obj)
- mono_profiler_allocation (obj);
- }
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()) && obj)
+ MONO_PROFILER_RAISE (gc_allocation, (obj));
return obj;
}
{
MonoObject *obj = sgen_alloc_obj_mature (vtable, size);
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) {
- if (obj)
- mono_profiler_allocation (obj);
- }
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()) && obj)
+ MONO_PROFILER_RAISE (gc_allocation, (obj));
return obj;
}
static MonoMethod* alloc_method_cache [ATYPE_NUM];
static MonoMethod* slowpath_alloc_method_cache [ATYPE_NUM];
+static MonoMethod* profiler_alloc_method_cache [ATYPE_NUM];
static gboolean use_managed_allocator = TRUE;
#ifdef MANAGED_ALLOCATION
{
int p_var, size_var, real_size_var, thread_var G_GNUC_UNUSED;
gboolean slowpath = variant == MANAGED_ALLOCATOR_SLOW_PATH;
+ gboolean profiler = variant == MANAGED_ALLOCATOR_PROFILER;
guint32 fastpath_branch, max_size_branch, no_oom_branch;
MonoMethodBuilder *mb;
MonoMethod *res;
mono_register_jit_icall (mono_gc_alloc_obj, "mono_gc_alloc_obj", mono_create_icall_signature ("object ptr int"), FALSE);
mono_register_jit_icall (mono_gc_alloc_vector, "mono_gc_alloc_vector", mono_create_icall_signature ("object ptr int int"), FALSE);
mono_register_jit_icall (mono_gc_alloc_string, "mono_gc_alloc_string", mono_create_icall_signature ("object ptr int int32"), FALSE);
+ mono_register_jit_icall (mono_profiler_raise_gc_allocation, "mono_profiler_raise_gc_allocation", mono_create_icall_signature ("void object"), FALSE);
registered = TRUE;
}
if (atype == ATYPE_SMALL) {
- name = slowpath ? "SlowAllocSmall" : "AllocSmall";
+ name = slowpath ? "SlowAllocSmall" : (profiler ? "ProfilerAllocSmall" : "AllocSmall");
} else if (atype == ATYPE_NORMAL) {
- name = slowpath ? "SlowAlloc" : "Alloc";
+ name = slowpath ? "SlowAlloc" : (profiler ? "ProfilerAlloc" : "Alloc");
} else if (atype == ATYPE_VECTOR) {
- name = slowpath ? "SlowAllocVector" : "AllocVector";
+ name = slowpath ? "SlowAllocVector" : (profiler ? "ProfilerAllocVector" : "AllocVector");
} else if (atype == ATYPE_STRING) {
- name = slowpath ? "SlowAllocString" : "AllocString";
+ name = slowpath ? "SlowAllocString" : (profiler ? "ProfilerAllocString" : "AllocString");
} else {
g_assert_not_reached ();
}
mono_mb_emit_ldloc (mb, p_var);
done:
+
+ /*
+ * It's important that we do this outside of the critical region as we
+ * will be invoking arbitrary code.
+ */
+ if (profiler) {
+ /*
+ * if (G_UNLIKELY (*&mono_profiler_state.gc_allocation_count)) {
+ * mono_profiler_raise_gc_allocation (p);
+ * }
+ */
+
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT);
+ mono_mb_emit_byte (mb, CEE_LDIND_U4);
+
+ int prof_br = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
+
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
+ mono_mb_emit_byte (mb, CEE_DUP);
+ mono_mb_emit_icall (mb, mono_profiler_raise_gc_allocation);
+
+ mono_mb_patch_short_branch (mb, prof_br);
+ }
+
mono_mb_emit_byte (mb, CEE_RET);
#endif
mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean known_instance_size)
{
#ifdef MANAGED_ALLOCATION
+ ManagedAllocatorVariant variant = mono_profiler_allocations_enabled () ?
+ MANAGED_ALLOCATOR_PROFILER : MANAGED_ALLOCATOR_REGULAR;
+
if (collect_before_allocs)
return NULL;
if (klass->instance_size > tlab_size)
return NULL;
if (klass->rank)
return NULL;
- if (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS)
- return NULL;
if (klass->byval_arg.type == MONO_TYPE_STRING)
- return mono_gc_get_managed_allocator_by_type (ATYPE_STRING, MANAGED_ALLOCATOR_REGULAR);
+ return mono_gc_get_managed_allocator_by_type (ATYPE_STRING, variant);
/* Generic classes have dynamic field and can go above MAX_SMALL_OBJ_SIZE. */
if (known_instance_size)
- return mono_gc_get_managed_allocator_by_type (ATYPE_SMALL, MANAGED_ALLOCATOR_REGULAR);
+ return mono_gc_get_managed_allocator_by_type (ATYPE_SMALL, variant);
else
- return mono_gc_get_managed_allocator_by_type (ATYPE_NORMAL, MANAGED_ALLOCATOR_REGULAR);
+ return mono_gc_get_managed_allocator_by_type (ATYPE_NORMAL, variant);
#else
return NULL;
#endif
#ifdef MANAGED_ALLOCATION
if (klass->rank != 1)
return NULL;
- if (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS)
- return NULL;
if (has_per_allocation_action)
return NULL;
g_assert (!mono_class_has_finalizer (klass) && !mono_class_is_marshalbyref (klass));
- return mono_gc_get_managed_allocator_by_type (ATYPE_VECTOR, MANAGED_ALLOCATOR_REGULAR);
+ return mono_gc_get_managed_allocator_by_type (ATYPE_VECTOR, mono_profiler_allocations_enabled () ?
+ MANAGED_ALLOCATOR_PROFILER : MANAGED_ALLOCATOR_REGULAR);
#else
return NULL;
#endif
MonoMethod *res;
MonoMethod **cache;
- if (variant == MANAGED_ALLOCATOR_REGULAR && !use_managed_allocator)
+ if (variant != MANAGED_ALLOCATOR_SLOW_PATH && !use_managed_allocator)
return NULL;
switch (variant) {
case MANAGED_ALLOCATOR_REGULAR: cache = alloc_method_cache; break;
case MANAGED_ALLOCATOR_SLOW_PATH: cache = slowpath_alloc_method_cache; break;
+ case MANAGED_ALLOCATOR_PROFILER: cache = profiler_alloc_method_cache; break;
default: g_assert_not_reached (); break;
}
int i;
for (i = 0; i < ATYPE_NUM; ++i)
- if (method == alloc_method_cache [i] || method == slowpath_alloc_method_cache [i])
+ if (method == alloc_method_cache [i] || method == slowpath_alloc_method_cache [i] || method == profiler_alloc_method_cache [i])
return TRUE;
return FALSE;
}
int i;
for (i = 0; i < ATYPE_NUM; ++i)
- if (alloc_method_cache [i] || slowpath_alloc_method_cache [i])
+ if (alloc_method_cache [i] || slowpath_alloc_method_cache [i] || profiler_alloc_method_cache [i])
return TRUE;
return FALSE;
}
UNLOCK_GC;
done:
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
- mono_profiler_allocation (&arr->obj);
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+ MONO_PROFILER_RAISE (gc_allocation, (&arr->obj));
SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Vector has incorrect size.");
return arr;
UNLOCK_GC;
done:
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
- mono_profiler_allocation (&arr->obj);
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+ MONO_PROFILER_RAISE (gc_allocation, (&arr->obj));
SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Array has incorrect size.");
return arr;
UNLOCK_GC;
done:
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
- mono_profiler_allocation (&str->object);
+ if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+ MONO_PROFILER_RAISE (gc_allocation, (&str->object));
return str;
}
{
if (!report->count)
return;
- mono_profiler_gc_roots (report->count, report->objects, report->root_types, report->extra_info);
+ MONO_PROFILER_RAISE (gc_roots, ((MonoObject **) report->objects, (MonoProfilerGCRootType *) report->root_types, report->extra_info, report->count));
report->count = 0;
}
void
sgen_client_nursery_objects_pinned (void **definitely_pinned, int count)
{
- if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS) {
+ if (MONO_PROFILER_ENABLED (gc_roots)) {
GCRootReport report;
int idx;
report.count = 0;
for (idx = 0; idx < count; ++idx)
- add_profile_gc_root (&report, definitely_pinned [idx], MONO_PROFILE_GC_ROOT_PINNING | MONO_PROFILE_GC_ROOT_MISC, 0);
+ add_profile_gc_root (&report, definitely_pinned [idx], MONO_PROFILER_GC_ROOT_PINNING | MONO_PROFILER_GC_ROOT_MISC, 0);
notify_gc_roots (&report);
}
}
void *obj = queue->data [i];
if (!obj)
continue;
- add_profile_gc_root (&report, obj, MONO_PROFILE_GC_ROOT_FINALIZER, 0);
+ add_profile_gc_root (&report, obj, MONO_PROFILER_GC_ROOT_FINALIZER, 0);
}
notify_gc_roots (&report);
}
single_arg_report_root (MonoObject **obj, void *gc_data)
{
if (*obj)
- add_profile_gc_root (root_report, *obj, MONO_PROFILE_GC_ROOT_OTHER, 0);
+ add_profile_gc_root (root_report, *obj, MONO_PROFILER_GC_ROOT_OTHER, 0);
}
static void
desc >>= ROOT_DESC_TYPE_SHIFT;
while (desc) {
if ((desc & 1) && *start_root) {
- add_profile_gc_root (report, *start_root, MONO_PROFILE_GC_ROOT_OTHER, 0);
+ add_profile_gc_root (report, *start_root, MONO_PROFILER_GC_ROOT_OTHER, 0);
}
desc >>= 1;
start_root++;
void **objptr = start_run;
while (bmap) {
if ((bmap & 1) && *objptr) {
- add_profile_gc_root (report, *objptr, MONO_PROFILE_GC_ROOT_OTHER, 0);
+ add_profile_gc_root (report, *objptr, MONO_PROFILER_GC_ROOT_OTHER, 0);
}
bmap >>= 1;
++objptr;
for (p = start_root; p < end_root; p++) {
if (*p)
- add_profile_gc_root (report, *p, MONO_PROFILE_GC_ROOT_OTHER, 0);
+ add_profile_gc_root (report, *p, MONO_PROFILER_GC_ROOT_OTHER, 0);
}
break;
}
void
sgen_client_collecting_minor (SgenPointerQueue *fin_ready_queue, SgenPointerQueue *critical_fin_queue)
{
- if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+ if (MONO_PROFILER_ENABLED (gc_roots))
report_registered_roots ();
- if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+
+ if (MONO_PROFILER_ENABLED (gc_roots))
report_finalizer_roots (fin_ready_queue, critical_fin_queue);
}
void
sgen_client_collecting_major_1 (void)
{
- profile_roots = mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS;
+ profile_roots = MONO_PROFILER_ENABLED (gc_roots);
memset (&major_root_report, 0, sizeof (GCRootReport));
}
sgen_client_pinned_los_object (GCObject *obj)
{
if (profile_roots)
- add_profile_gc_root (&major_root_report, (char*)obj, MONO_PROFILE_GC_ROOT_PINNING | MONO_PROFILE_GC_ROOT_MISC, 0);
+ add_profile_gc_root (&major_root_report, (char*)obj, MONO_PROFILER_GC_ROOT_PINNING | MONO_PROFILER_GC_ROOT_MISC, 0);
}
void
if (profile_roots)
notify_gc_roots (&major_root_report);
- if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+ if (MONO_PROFILER_ENABLED (gc_roots))
report_registered_roots ();
}
void
sgen_client_collecting_major_3 (SgenPointerQueue *fin_ready_queue, SgenPointerQueue *critical_fin_queue)
{
- if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+ if (MONO_PROFILER_ENABLED (gc_roots))
report_finalizer_roots (fin_ready_queue, critical_fin_queue);
}
sgen_pointer_queue_add (&moved_objects_queue, destination);
} else {
if (moved_objects_idx == MOVED_OBJECTS_NUM) {
- mono_profiler_gc_moves (moved_objects, moved_objects_idx);
+ MONO_PROFILER_RAISE (gc_moves, ((MonoObject **) moved_objects, moved_objects_idx));
moved_objects_idx = 0;
}
}
if (moved_objects_idx) {
- mono_profiler_gc_moves (moved_objects, moved_objects_idx);
+ MONO_PROFILER_RAISE (gc_moves, ((MonoObject **) moved_objects, moved_objects_idx));
moved_objects_idx = 0;
}
}
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_num_handles++;
#endif
- mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_CREATED, handle_type, handle, obj);
+
+ MONO_PROFILER_RAISE (gc_handle_created, (handle, handle_type, obj));
}
void
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_num_handles--;
#endif
- mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_DESTROYED, handle_type, handle, NULL);
+
+ MONO_PROFILER_RAISE (gc_handle_deleted, (handle, handle_type));
}
void
{
TV_DECLARE (end_handshake);
- mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD, generation));
acquire_gc_locks ();
- mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation));
/* We start to scan after locks are taking, this ensures we won't be interrupted. */
sgen_process_togglerefs ();
SGEN_LOG (3, "world stopped");
- mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_STOP_WORLD, generation));
TV_GETTIME (end_handshake);
time_stop_world += TV_ELAPSED (stop_world_time, end_handshake);
/* notify the profiler of the leftovers */
/* FIXME this is the wrong spot at we can STW for non collection reasons. */
- if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
+ if (MONO_PROFILER_ENABLED (gc_moves))
mono_sgen_gc_event_moves ();
- mono_profiler_gc_event (MONO_GC_EVENT_PRE_START_WORLD, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_START_WORLD, generation));
FOREACH_THREAD (info) {
info->client_info.stack_start = NULL;
SGEN_LOG (2, "restarted (pause time: %d usec, max: %d)", (int)usec, (int)max_pause_usec);
- mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD, generation));
/*
* We must release the thread info suspend lock after doing
*/
release_gc_locks ();
- mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation);
+ MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation));
*stw_time = usec;
}
#include <mono/metadata/object-internals.h>
+/* Keep in sync with System.Reflection.Emit.AssemblyBuilderAccess */
+enum MonoAssemblyBuilderAccess {
+ MonoAssemblyBuilderAccess_Run = 1, /* 0b0001 */
+ MonoAssemblyBuilderAccess_Save = 2, /* 0b0010 */
+ MonoAssemblyBuilderAccess_RunAndSave = 3, /* Run | Save */
+ MonoAssemblyBuilderAccess_ReflectionOnly = 6, /* Refonly | Save */
+ MonoAssemblyBuilderAccess_RunAndCollect = 9, /* Collect | Run */
+};
+
typedef struct _ArrayMethod ArrayMethod;
typedef struct {
#ifndef DISABLE_REFLECTION_EMIT
+static gboolean
+assemblybuilderaccess_can_refonlyload (guint32 access)
+{
+ return (access & 0x4) != 0;
+}
+
+static gboolean
+assemblybuilderaccess_can_run (guint32 access)
+{
+ return (access & MonoAssemblyBuilderAccess_Run) != 0;
+}
+
+static gboolean
+assemblybuilderaccess_can_save (guint32 access)
+{
+ return (access & MonoAssemblyBuilderAccess_Save) != 0;
+}
+
+
/*
* mono_reflection_dynimage_basic_init:
* @assembly: an assembly builder object
assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
- mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (assembly_loading, (&assembly->assembly));
assembly->assembly.ref_count = 1;
assembly->assembly.dynamic = TRUE;
assembly->assembly.aname.revision = 0;
}
- assembly->run = assemblyb->access != 2;
- assembly->save = assemblyb->access != 1;
+ assembly->assembly.ref_only = assemblybuilderaccess_can_refonlyload (assemblyb->access);
+ assembly->run = assemblybuilderaccess_can_run (assemblyb->access);
+ assembly->save = assemblybuilderaccess_can_save (assemblyb->access);
assembly->domain = domain;
char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
- mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (assembly_loaded, (&assembly->assembly));
mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
}
klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx;
mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
- mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+ MONO_PROFILER_RAISE (class_loading, (klass));
klass->element_class = klass;
/*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (class_loaded, (klass));
leave:
mono_loader_unlock ();
void
mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
{
- mono_gc_deregister_root ((char*) &entry->gparam);
+ MONO_GC_UNREGISTER_ROOT_IF_MOVING (entry->gparam);
g_free (entry);
}
#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 ()
void mono_threads_join_threads (void);
void mono_thread_join (gpointer tid);
-void mono_thread_detach_internal (MonoInternalThread *thread);
-
void ves_icall_System_Threading_Thread_GetStackTraces (MonoArray **out_threads, MonoArray **out_stack_traces);
MONO_API gpointer
return TRUE;
}
+static void
+mono_thread_detach_internal (MonoInternalThread *thread)
+{
+ gboolean removed;
+
+ g_assert (thread != NULL);
+ SET_CURRENT_OBJECT (thread);
+
+ THREAD_DEBUG (g_message ("%s: mono_thread_detach for %p (%"G_GSIZE_FORMAT")", __func__, thread, (gsize)thread->tid));
+
+#ifndef HOST_WIN32
+ mono_w32mutex_abandon ();
+#endif
+
+ if (thread->abort_state_handle) {
+ mono_gchandle_free (thread->abort_state_handle);
+ thread->abort_state_handle = 0;
+ }
+
+ thread->abort_exc = NULL;
+ thread->current_appcontext = NULL;
+
+ /*
+ * thread->synch_cs can be NULL if this was called after
+ * ves_icall_System_Threading_InternalThread_Thread_free_internal.
+ * This can happen only during shutdown.
+ * The shutting_down flag is not always set, so we can't assert on it.
+ */
+ if (thread->synch_cs)
+ LOCK_THREAD (thread);
+
+ thread->state |= ThreadState_Stopped;
+ thread->state &= ~ThreadState_Background;
+
+ if (thread->synch_cs)
+ UNLOCK_THREAD (thread);
+
+ /*
+ An interruption request has leaked to cleanup. Adjust the global counter.
+
+ This can happen is the abort source thread finds the abortee (this) thread
+ in unmanaged code. If this thread never trips back to managed code or check
+ the local flag it will be left set and positively unbalance the global counter.
+
+ Leaving the counter unbalanced will cause a performance degradation since all threads
+ will now keep checking their local flags all the time.
+ */
+ mono_thread_clear_interruption_requested (thread);
+
+ mono_threads_lock ();
+
+ if (!threads) {
+ removed = FALSE;
+ } else if (mono_g_hash_table_lookup (threads, (gpointer)thread->tid) != thread) {
+ /* We have to check whether the thread object for the
+ * tid is still the same in the table because the
+ * thread might have been destroyed and the tid reused
+ * in the meantime, in which case the tid would be in
+ * the table, but with another thread object.
+ */
+ removed = FALSE;
+ } else {
+ mono_g_hash_table_remove (threads, (gpointer)thread->tid);
+ removed = TRUE;
+ }
+
+ mono_threads_unlock ();
+
+ /* Don't close the handle here, wait for the object finalizer
+ * to do it. Otherwise, the following race condition applies:
+ *
+ * 1) Thread exits (and mono_thread_detach_internal() closes the handle)
+ *
+ * 2) Some other handle is reassigned the same slot
+ *
+ * 3) Another thread tries to join the first thread, and
+ * blocks waiting for the reassigned handle to be signalled
+ * (which might never happen). This is possible, because the
+ * thread calling Join() still has a reference to the first
+ * thread's object.
+ */
+
+ /* if the thread is not in the hash it has been removed already */
+ if (!removed) {
+ mono_domain_unset ();
+ mono_memory_barrier ();
+
+ if (mono_thread_cleanup_fn)
+ mono_thread_cleanup_fn (thread_get_tid (thread));
+
+ goto done;
+ }
+
+ mono_release_type_locks (thread);
+
+ /* Can happen when we attach the profiler helper thread in order to heapshot. */
+ if (!mono_thread_info_lookup (MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid))->tools_thread)
+ MONO_PROFILER_RAISE (thread_stopped, (thread->tid));
+
+ mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
+
+ /*
+ * This will signal async signal handlers that the thread has exited.
+ * The profiler callback needs this to be set, so it cannot be done earlier.
+ */
+ mono_domain_unset ();
+ mono_memory_barrier ();
+
+ if (thread == mono_thread_internal_current ())
+ mono_thread_pop_appdomain_ref ();
+
+ mono_free_static_data (thread->static_data);
+ thread->static_data = NULL;
+ ref_stack_destroy (thread->appdomain_refs);
+ thread->appdomain_refs = NULL;
+
+ g_assert (thread->suspended);
+ mono_os_event_destroy (thread->suspended);
+ g_free (thread->suspended);
+ thread->suspended = NULL;
+
+ if (mono_thread_cleanup_fn)
+ mono_thread_cleanup_fn (thread_get_tid (thread));
+
+ mono_memory_barrier ();
+
+ if (mono_gc_is_moving ()) {
+ MONO_GC_UNREGISTER_ROOT (thread->thread_pinning_ref);
+ thread->thread_pinning_ref = NULL;
+ }
+
+done:
+ SET_CURRENT_OBJECT (NULL);
+ mono_domain_unset ();
+
+ mono_thread_info_unset_internal_thread_gchandle ((MonoThreadInfo*) thread->thread_info);
+
+ /* Don't need to close the handle to this thread, even though we took a
+ * reference in mono_thread_attach (), because the GC will do it
+ * when the Thread object is finalised.
+ */
+}
+
typedef struct {
gint32 ref;
MonoThread *thread;
* to lock the thread, and the lock is held by thread_start () which waits for
* start_notify.
*/
- mono_profiler_thread_start (tid);
+ MONO_PROFILER_RAISE (thread_started, (tid));
/* if the name was set before starting, we didn't invoke the profiler callback */
if (internal->name) {
char *tname = g_utf16_to_utf8 (internal->name, internal->name_len, NULL, NULL, NULL);
- mono_profiler_thread_name (internal->tid, tname);
+ MONO_PROFILER_RAISE (thread_name, (internal->tid, tname));
mono_native_thread_set_name (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid), tname);
g_free (tname);
}
/* Can happen when we attach the profiler helper thread in order to heapshot. */
if (!mono_thread_info_current ()->tools_thread)
- // FIXME: Need a separate callback
- mono_profiler_thread_start (MONO_NATIVE_THREAD_ID_TO_UINT (tid));
+ MONO_PROFILER_RAISE (thread_started, (MONO_NATIVE_THREAD_ID_TO_UINT (tid)));
return thread;
}
return mono_thread_attach_full (domain, FALSE);
}
-void
-mono_thread_detach_internal (MonoInternalThread *thread)
-{
- gboolean removed;
-
- g_assert (thread != NULL);
- SET_CURRENT_OBJECT (thread);
-
- THREAD_DEBUG (g_message ("%s: mono_thread_detach for %p (%"G_GSIZE_FORMAT")", __func__, thread, (gsize)thread->tid));
-
-#ifndef HOST_WIN32
- mono_w32mutex_abandon ();
-#endif
-
- if (thread->abort_state_handle) {
- mono_gchandle_free (thread->abort_state_handle);
- thread->abort_state_handle = 0;
- }
-
- thread->abort_exc = NULL;
- thread->current_appcontext = NULL;
-
- /*
- * thread->synch_cs can be NULL if this was called after
- * ves_icall_System_Threading_InternalThread_Thread_free_internal.
- * This can happen only during shutdown.
- * The shutting_down flag is not always set, so we can't assert on it.
- */
- if (thread->synch_cs)
- LOCK_THREAD (thread);
-
- thread->state |= ThreadState_Stopped;
- thread->state &= ~ThreadState_Background;
-
- if (thread->synch_cs)
- UNLOCK_THREAD (thread);
-
- /*
- An interruption request has leaked to cleanup. Adjust the global counter.
-
- This can happen is the abort source thread finds the abortee (this) thread
- in unmanaged code. If this thread never trips back to managed code or check
- the local flag it will be left set and positively unbalance the global counter.
-
- Leaving the counter unbalanced will cause a performance degradation since all threads
- will now keep checking their local flags all the time.
- */
- mono_thread_clear_interruption_requested (thread);
-
- mono_threads_lock ();
-
- if (!threads) {
- removed = FALSE;
- } else if (mono_g_hash_table_lookup (threads, (gpointer)thread->tid) != thread) {
- /* We have to check whether the thread object for the
- * tid is still the same in the table because the
- * thread might have been destroyed and the tid reused
- * in the meantime, in which case the tid would be in
- * the table, but with another thread object.
- */
- removed = FALSE;
- } else {
- mono_g_hash_table_remove (threads, (gpointer)thread->tid);
- removed = TRUE;
- }
-
- mono_threads_unlock ();
-
- /* Don't close the handle here, wait for the object finalizer
- * to do it. Otherwise, the following race condition applies:
- *
- * 1) Thread exits (and mono_thread_detach_internal() closes the handle)
- *
- * 2) Some other handle is reassigned the same slot
- *
- * 3) Another thread tries to join the first thread, and
- * blocks waiting for the reassigned handle to be signalled
- * (which might never happen). This is possible, because the
- * thread calling Join() still has a reference to the first
- * thread's object.
- */
-
- /* if the thread is not in the hash it has been removed already */
- if (!removed) {
- mono_domain_unset ();
- mono_memory_barrier ();
-
- if (mono_thread_cleanup_fn)
- mono_thread_cleanup_fn (thread_get_tid (thread));
-
- goto done;
- }
-
- mono_release_type_locks (thread);
-
- /* Can happen when we attach the profiler helper thread in order to heapshot. */
- if (!mono_thread_info_lookup (MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid))->tools_thread)
- mono_profiler_thread_end (thread->tid);
-
- mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
-
- /*
- * This will signal async signal handlers that the thread has exited.
- * The profiler callback needs this to be set, so it cannot be done earlier.
- */
- mono_domain_unset ();
- mono_memory_barrier ();
-
- if (thread == mono_thread_internal_current ())
- mono_thread_pop_appdomain_ref ();
-
- mono_free_static_data (thread->static_data);
- thread->static_data = NULL;
- ref_stack_destroy (thread->appdomain_refs);
- thread->appdomain_refs = NULL;
-
- g_assert (thread->suspended);
- mono_os_event_destroy (thread->suspended);
- g_free (thread->suspended);
- thread->suspended = NULL;
-
- if (mono_thread_cleanup_fn)
- mono_thread_cleanup_fn (thread_get_tid (thread));
-
- mono_memory_barrier ();
-
- if (mono_gc_is_moving ()) {
- MONO_GC_UNREGISTER_ROOT (thread->thread_pinning_ref);
- thread->thread_pinning_ref = NULL;
- }
-
-done:
- SET_CURRENT_OBJECT (NULL);
- mono_domain_unset ();
-
- mono_thread_info_unset_internal_thread_gchandle ((MonoThreadInfo*) thread->thread_info);
-
- /* Don't need to close the handle to this thread, even though we took a
- * reference in mono_thread_attach (), because the GC will do it
- * when the Thread object is finalised.
- */
-}
-
/**
* mono_thread_detach:
*/
if (this_obj->name && this_obj->tid) {
char *tname = mono_string_to_utf8_checked (name, error);
return_if_nok (error);
- mono_profiler_thread_name (this_obj->tid, tname);
+ MONO_PROFILER_RAISE (thread_name, (this_obj->tid, tname));
mono_native_thread_set_name (thread_get_tid (this_obj), tname);
mono_free (tname);
}
mono_threads_unlock ();
- mono_profiler_context_loaded (ctx);
+ MONO_PROFILER_RAISE (context_loaded, (ctx));
}
void
//g_print ("Releasing context %d in domain %d\n", ctx->context_id, ctx->domain_id);
- mono_profiler_context_unloaded (ctx);
+ MONO_PROFILER_RAISE (context_unloaded, (ctx));
}
void
#define WSAEHOSTDOWN 10064
#define WSAEHOSTUNREACH 10065
#define WSASYSCALLFAILURE 10107
+#define WSAENXIO 100001
#endif
mono_w32handle_unlock_handle (handle);
MONO_ENTER_GC_SAFE;
- mono_w32handle_unref (handle);
+ mono_w32handle_close (handle);
MONO_EXIT_GC_SAFE;
return(TRUE);
g_warning ("%s: error creating pipe write handle", __func__);
MONO_ENTER_GC_SAFE;
- mono_w32handle_unref (read_handle);
+ mono_w32handle_close (read_handle);
close (filedes[0]);
close (filedes[1]);
{ DRIVE_RAMDISK, "fdesc" },
{ DRIVE_REMOTE, "ftp" },
{ DRIVE_FIXED, "hfs" },
+ { DRIVE_FIXED, "apfs" },
{ DRIVE_FIXED, "msdos" },
{ DRIVE_REMOTE, "nfs" },
{ DRIVE_FIXED, "ntfs" },
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;
ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
MONO_EXIT_GC_SAFE;
#else
- mono_w32handle_ref (source_handle);
- *target_handle = source_handle;
+ *target_handle = mono_w32handle_duplicate (source_handle);
ret = TRUE;
#endif
__func__, handle);
/* we do not want the handle to be destroyed before we return it */
- mono_w32handle_ref (handle);
-
- search_data->ret = handle;
+ search_data->ret = mono_w32handle_duplicate (handle);
}
return TRUE;
MonoW32HandleType type;
guint ref;
gboolean signalled;
+ gboolean in_use;
mono_mutex_t signal_mutex;
mono_cond_t signal_cond;
gpointer specific;
return handle_data->signalled;
}
+static void
+mono_w32handle_set_in_use (gpointer handle, gboolean in_use)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_assert_not_reached ();
+
+ handle_data->in_use = in_use;
+}
+
static void
mono_w32handle_lock_signal_mutex (void)
{
mono_os_mutex_unlock (&global_signal_mutex);
}
+static void
+mono_w32handle_ref (gpointer handle);
+
+static void
+mono_w32handle_unref (gpointer handle);
+
void
mono_w32handle_lock_handle (gpointer handle)
{
void
mono_w32handle_cleanup (void)
{
- int i, j, k;
+ int i;
g_assert (!shutting_down);
shutting_down = TRUE;
- /* Every shared handle we were using ought really to be closed
- * by now, but to make sure just blow them all away. The
- * exiting finalizer thread in particular races us to the
- * program exit and doesn't always win, so it can be left
- * cluttering up the shared file. Anything else left over is
- * really a bug.
- */
- for(i = SLOT_INDEX (0); private_handles[i] != NULL; i++) {
- for(j = SLOT_OFFSET (0); j < HANDLE_PER_SLOT; j++) {
- MonoW32HandleBase *handle_data = &private_handles[i][j];
- gpointer handle = GINT_TO_POINTER (i*HANDLE_PER_SLOT+j);
-
- for(k = handle_data->ref; k > 0; k--) {
- mono_w32handle_unref (handle);
- }
- }
- }
-
for (i = 0; i < SLOT_MAX; ++i)
g_free (private_handles [i]);
}
fd_index = SLOT_INDEX (fd);
fd_offset = SLOT_OFFSET (fd);
+ mono_os_mutex_lock (&scan_mutex);
/* Initialize the array entries on demand */
if (!private_handles [fd_index]) {
- mono_os_mutex_lock (&scan_mutex);
-
if (!private_handles [fd_index])
private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
-
- mono_os_mutex_unlock (&scan_mutex);
}
handle_data = &private_handles [fd_index][fd_offset];
if (handle_data->type != MONO_W32HANDLE_UNUSED) {
+ mono_os_mutex_unlock (&scan_mutex);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is already in use", __func__, mono_w32handle_ops_typename (type));
/* FIXME: clean up this handle? We can't do anything
* with the fd, cos thats the new one
mono_w32handle_init_handle (handle_data, type, handle_specific);
+ mono_os_mutex_unlock (&scan_mutex);
+
return(GUINT_TO_POINTER(fd));
}
+static gboolean
+mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
+
+static gboolean
+mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data);
+
+static void
+w32handle_destroy (gpointer handle);
+
+gpointer
+mono_w32handle_duplicate (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (handle == INVALID_HANDLE_VALUE)
+ return handle;
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ return INVALID_HANDLE_VALUE;
+ if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE)
+ return handle;
+
+ if (!mono_w32handle_ref_core (handle, handle_data))
+ g_error ("%s: failed to ref handle %p", __func__, handle);
+
+ return handle;
+}
+
gboolean
mono_w32handle_close (gpointer handle)
{
+ MonoW32HandleBase *handle_data;
+ gboolean destroy;
+
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
- if (handle == (gpointer) 0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) {
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ return FALSE;
+ if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE) {
/* Problem: because we map file descriptors to the
* same-numbered handle we can't tell the difference
* between a bogus handle and the handle to stdin.
return FALSE;
}
- mono_w32handle_unref (handle);
+ destroy = mono_w32handle_unref_core (handle, handle_data);
+ if (destroy)
+ w32handle_destroy (handle);
+
return TRUE;
}
return(TRUE);
}
-static gboolean
-mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
-
-static gboolean
-mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data);
-
-static void
-w32handle_destroy (gpointer handle);
-
void
mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data)
{
return new == 0;
}
-void mono_w32handle_ref (gpointer handle)
+static void
+mono_w32handle_ref (gpointer handle)
{
MonoW32HandleBase *handle_data;
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to ref handle %p, unknown handle", __func__, handle);
- return;
- }
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("%s: failed to ref handle %p, unknown handle", __func__, handle);
if (!mono_w32handle_ref_core (handle, handle_data))
g_error ("%s: failed to ref handle %p", __func__, handle);
if (!mono_w32handle_lookup_data (handle, &handle_data))
g_error ("%s: unknown handle %p", __func__, handle);
+ g_assert (!handle_data->in_use);
+
type = handle_data->type;
handle_specific = handle_data->specific;
close_func (handle, handle_specific);
}
+ memset (handle_specific, 0, mono_w32handle_ops_typesize (type));
+
g_free (handle_specific);
}
/* The handle must not be locked on entry to this function */
-void
+static void
mono_w32handle_unref (gpointer handle)
{
MonoW32HandleBase *handle_data;
gboolean destroy;
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to unref handle %p, unknown handle",
- __func__, handle);
- return;
- }
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("%s: failed to unref handle %p, unknown handle", __func__, handle);
destroy = mono_w32handle_unref_core (handle, handle_data);
if (destroy)
mono_os_cond_broadcast (cond);
mono_os_mutex_unlock (mutex);
- mono_w32handle_unref (handle);
+ mono_w32handle_close (handle);
}
static int
mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
{
MonoW32HandleBase *handle_data;
+ gpointer handle_duplicate;
int res;
if (!mono_w32handle_lookup_data (handle, &handle_data))
*alerted = FALSE;
if (alerted) {
- mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
- if (*alerted)
+ mono_thread_info_install_interrupt (signal_handle_and_unref, handle_duplicate = mono_w32handle_duplicate (handle), alerted);
+ if (*alerted) {
+ mono_w32handle_close (handle_duplicate);
return 0;
- mono_w32handle_ref (handle);
+ }
}
res = mono_w32handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted);
if (alerted) {
mono_thread_info_uninstall_interrupt (alerted);
if (!*alerted) {
- /* if it is alerted, then the handle is unref in the interrupt callback */
- mono_w32handle_unref (handle);
+ /* if it is alerted, then the handle_duplicate is closed in the interrupt callback */
+ mono_w32handle_close (handle_duplicate);
}
}
g_error ("cannot dump unknown handle %p", handle);
g_print ("%p [%7s] signalled: %5s ref: %3d ",
- handle, mono_w32handle_ops_typename (handle_data->type), handle_data->signalled ? "true" : "false", handle_data->ref);
+ handle, mono_w32handle_ops_typename (handle_data->type), handle_data->signalled ? "true" : "false", handle_data->ref - 1 /* foreach increase ref by 1 */);
mono_w32handle_ops_details (handle_data->type, handle_data->specific);
g_print ("\n");
if (timeout != MONO_INFINITE_WAIT)
start = mono_msec_ticks ();
+ mono_w32handle_set_in_use (handle, TRUE);
+
for (;;) {
gint waited;
}
done:
+ mono_w32handle_set_in_use (handle, FALSE);
+
mono_w32handle_unlock_handle (handle);
return ret;
gpointer
mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific);
+gpointer
+mono_w32handle_duplicate (gpointer handle);
+
gboolean
mono_w32handle_close (gpointer handle);
void
mono_w32handle_dump (void);
-void
-mono_w32handle_ref (gpointer handle);
-
-void
-mono_w32handle_unref (gpointer handle);
-
void
mono_w32handle_register_capabilities (MonoW32HandleType type, MonoW32HandleCapability caps);
static void
thread_own_mutex (MonoInternalThread *internal, gpointer handle)
{
- mono_w32handle_ref (handle);
-
/* if we are not on the current thread, there is a
* race condition when allocating internal->owned_mutexes */
g_assert (mono_thread_internal_is_current (internal));
if (!internal->owned_mutexes)
internal->owned_mutexes = g_ptr_array_new ();
- g_ptr_array_add (internal->owned_mutexes, handle);
+ g_ptr_array_add (internal->owned_mutexes, mono_w32handle_duplicate (handle));
}
static void
removed = g_ptr_array_remove (internal->owned_mutexes, handle);
g_assert (removed);
- mono_w32handle_unref (handle);
+ mono_w32handle_close (handle);
}
static void
/*
* Process describes processes we create.
* It contains a semaphore that can be waited on in order to wait
- * for process termination. It's accessed in our SIGCHLD handler,
- * when status is updated (and pid cleared, to not clash with
- * subsequent processes that may get executed).
+ * for process termination.
*/
typedef struct _Process {
pid_t pid; /* the pid of the process. This value is only valid until the process has exited. */
* the process has exited, so that the information there isn't lost.
*/
gpointer handle;
- gboolean freeable;
gboolean signalled;
struct _Process *next;
} Process;
static gchar *cli_launcher;
-/* The signal-safe logic to use processes goes like this:
- * - The list must be safe to traverse for the signal handler at all times.
- * It's safe to: prepend an entry (which is a single store to 'processes'),
- * unlink an entry (assuming the unlinked entry isn't freed and doesn't
- * change its 'next' pointer so that it can still be traversed).
- * When cleaning up we first unlink an entry, then we verify that
- * the read lock isn't locked. Then we can free the entry, since
- * we know that nobody is using the old version of the list (including
- * the unlinked entry).
- * We also need to lock when adding and cleaning up so that those two
- * operations don't mess with eachother. (This lock is not used in the
- * signal handler) */
static Process *processes;
static mono_mutex_t processes_mutex;
static gint32 cleaning_up;
Process *process;
Process *prev = NULL;
- GSList *finished = NULL;
- GSList *l;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
if (InterlockedCompareExchange (&cleaning_up, 1, 0) != 0)
return;
+ /*
+ * This needs to be done outside the lock but atomically, hence the CAS above.
+ */
for (process = processes; process; process = process->next) {
if (process->signalled && process->handle) {
/* This process has exited and we need to remove the artifical ref
* on the handle */
- mono_w32handle_unref (process->handle);
+ mono_w32handle_close (process->handle);
process->handle = NULL;
}
}
- /*
- * Remove processes which exited from the processes list.
- * We need to synchronize with the sigchld handler here, which runs
- * asynchronously. The handler requires that the processes list
- * remain valid.
- */
mono_os_mutex_lock (&processes_mutex);
- for (process = processes; process; process = process->next) {
- if (process->handle_count == 0 && process->freeable) {
+ for (process = processes; process;) {
+ Process *next = process->next;
+ if (process->handle_count == 0 && process->signalled) {
/*
* Unlink the entry.
- * This code can run parallel with the sigchld handler, but the
- * modifications it makes are safe.
*/
if (process == processes)
processes = process->next;
else
prev->next = process->next;
- finished = g_slist_prepend (finished, process);
+
+ mono_os_sem_destroy (&process->exit_sem);
+ g_free (process);
} else {
prev = process;
}
+ process = next;
}
- mono_memory_barrier ();
-
- for (l = finished; l; l = l->next) {
- /*
- * All the entries in the finished list are unlinked from processes, and
- * they have the 'finished' flag set, which means the sigchld handler is done
- * accessing them.
- */
- process = (Process *)l->data;
- mono_os_sem_destroy (&process->exit_sem);
- g_free (process);
- }
- g_slist_free (finished);
-
mono_os_mutex_unlock (&processes_mutex);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s done", __func__);
process_set_name (&process_handle);
current_process = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
- g_assert (current_process);
+ g_assert (current_process != INVALID_HANDLE_VALUE);
mono_os_mutex_init (&processes_mutex);
}
if (mono_w32handle_issignalled (handle))
return FALSE;
- mono_w32handle_ref (handle);
- foreach_data->handle = handle;
+ foreach_data->handle = mono_w32handle_duplicate (handle);
return TRUE;
}
#if HAVE_SIGACTION
MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context))
+{
+ /*
+ * Don't want to do any complicated processing here so just wake up the finalizer thread which will call
+ * mono_w32process_signal_finished ().
+ */
+ int old_errno = errno;
+
+ mono_gc_finalize_notify ();
+
+ errno = old_errno;
+}
+
+static void
+process_add_sigchld_handler (void)
+{
+ struct sigaction sa;
+
+ sa.sa_sigaction = mono_sigchld_signal_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO | SA_RESTART;
+ g_assert (sigaction (SIGCHLD, &sa, NULL) != -1);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "Added SIGCHLD handler");
+}
+
+#endif
+
+/*
+ * mono_w32process_signal_finished:
+ *
+ * Signal the exit semaphore for processes which have finished.
+ */
+void
+mono_w32process_signal_finished (void)
{
int status;
int pid;
if (pid <= 0)
break;
- /*
- * This can run concurrently with the code in the rest of this module.
- */
+ mono_os_mutex_lock (&processes_mutex);
+
for (process = processes; process; process = process->next) {
if (process->pid != pid)
continue;
process->signalled = TRUE;
process->status = status;
mono_os_sem_post (&process->exit_sem);
- mono_memory_barrier ();
- /* Mark this as freeable, the pointer becomes invalid afterwards */
- process->freeable = TRUE;
break;
}
- } while (1);
-}
-static void
-process_add_sigchld_handler (void)
-{
- struct sigaction sa;
-
- sa.sa_sigaction = mono_sigchld_signal_handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
- g_assert (sigaction (SIGCHLD, &sa, NULL) != -1);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "Added SIGCHLD handler");
+ mono_os_mutex_unlock (&processes_mutex);
+ } while (1);
}
-#endif
-
static gboolean
is_readable_or_executable (const char *prog)
{
/* Keep the process handle artificially alive until the process
* exits so that the information in the handle isn't lost. */
- mono_w32handle_ref (handle);
- process->handle = handle;
+ process->handle = mono_w32handle_duplicate (handle);
mono_os_mutex_lock (&processes_mutex);
process->next = processes;
{
}
+void
+mono_w32process_signal_finished (void)
+{
+}
+
#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
HANDLE
ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
void
mono_w32process_cleanup (void);
+void
+mono_w32process_signal_finished (void);
+
#ifndef HOST_WIN32
void
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));
endif
# This is needed for automake dependency generation
+if SUPPORT_NULLGC
+libgc_libs=
+libgc_static_libs=
+else
libgc_libs=$(monodir)/libgc/libmonogc.la
libgc_static_libs=$(monodir)/libgc/libmonogc-static.la
+endif
boehm_libs= \
$(monodir)/mono/metadata/libmonoruntime.la \
basic-calls.cs \
basic-long.cs \
bench.cs \
+ builtin-types.cs \
objects.cs \
arrays.cs \
basic-float.cs \
basic-float.exe \
basic-long.exe \
basic-calls.exe \
+ builtin-types.exe \
objects.exe \
arrays.exe \
basic-math.exe \
regtests_DISABLED =
if FULL_AOT_TESTS
-regtests_DISABLED +=
+regtests_DISABLED += builtin-types.exe
endif
regtests = $(filter-out $(regtests_DISABLED),$(regtests_UNIVERSAL))
basic-vectors.exe: basic-vectors.cs TestDriver.dll
$(MCS) -out:$@ $(CSFLAGS) $< -r:TestDriver.dll -r:$(CLASS)/System.Numerics.dll -r:$(CLASS)/System.Numerics.Vectors.dll
+builtin-types.exe: builtin-types.cs TestDriver.dll
+ $(MCS) -out:$@ $(CSFLAGS) -define:ARCH_$(shell echo $$((8 * $(SIZEOF_VOID_P)))) $< -r:TestDriver.dll
+
nacl.exe: nacl.cs TestDriver.dll
$(MCS) -out:$@ $(CSFLAGS) $< -r:TestDriver.dll -r:$(CLASS)/Mono.Simd.dll
add_method (acfg, m);
if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
add_method (acfg, m);
+ if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_PROFILER)))
+ add_method (acfg, m);
}
/* write barriers */
break;
case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
break;
+ case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
+ break;
case MONO_PATCH_INFO_RGCTX_FETCH:
case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
#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
case MONO_WRAPPER_ALLOC: {
int atype = decode_value (p, &p);
ManagedAllocatorVariant variant =
- mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS ?
- MANAGED_ALLOCATOR_SLOW_PATH : MANAGED_ALLOCATOR_REGULAR;
+ mono_profiler_allocations_enabled () ?
+ MANAGED_ALLOCATOR_PROFILER : MANAGED_ALLOCATOR_REGULAR;
ref->method = mono_gc_get_managed_allocator_by_type (atype, variant);
/* Try to fallback to the slow path version */
- if (!ref->method && variant == MANAGED_ALLOCATOR_REGULAR)
+ if (!ref->method)
ref->method = mono_gc_get_managed_allocator_by_type (atype, MANAGED_ALLOCATOR_SLOW_PATH);
if (!ref->method) {
mono_error_set_bad_image_name (error, module->aot_name, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
*/
return;
- if (image_is_dynamic (assembly->image) || assembly->ref_only)
+ if (image_is_dynamic (assembly->image) || assembly->ref_only || mono_domain_get () != mono_get_root_domain ())
return;
mono_aot_lock ();
g_slist_free (nesting [i]);
g_free (nesting);
}
+ jinfo->from_llvm = 1;
} else {
len = mono_jit_info_size (flags, num_clauses, num_holes);
jinfo = (MonoJitInfo *)alloc0_jit_info_data (domain, len, async);
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_GC_NURSERY_BITS:
+ case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
break;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
ji->data.index = decode_value (p, &p);
init_amodule_got (amodule);
- if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) {
- if (mono_aot_only)
- /* The caller cannot handle this */
- g_assert_not_reached ();
- return NULL;
- }
-
if (domain != mono_get_root_domain ())
/* Non shared AOT code can't be used in other appdomains */
return NULL;
amodule_unlock (amodule);
- if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) {
+ if (MONO_PROFILER_ENABLED (jit_begin) || MONO_PROFILER_ENABLED (jit_done)) {
MonoJitInfo *jinfo;
if (!method) {
if (!method)
return NULL;
}
- mono_profiler_method_jit (method);
+ MONO_PROFILER_RAISE (jit_begin, (method));
jinfo = mono_jit_info_table_find (domain, (char*)code);
g_assert (jinfo);
- mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (jit_done, (method, jinfo));
}
return code;
--- /dev/null
+// #define ARCH_32
+#define NINT_JIT_OPTIMIZED
+
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+
+public class BuiltinTests {
+ static int test_0_nint_ctor ()
+ {
+ var x = new nint (10);
+ var y = new nint (x);
+ var z = new nint (new nint (20));
+ if ((int)x != 10)
+ return 1;
+ if ((int)y != 10)
+ return 2;
+ if ((int)z != 20)
+ return 3;
+ return 0;
+ }
+
+ static int test_0_nint_casts ()
+ {
+ var x = (nint)10;
+ var y = (nint)20L;
+
+ if ((int)x != 10)
+ return 1;
+ if ((long)x != 10L)
+ return 2;
+ if ((int)y != 20)
+ return 3;
+ if ((long)y != 20L)
+ return 4;
+ return 0;
+ }
+
+ static int test_0_nint_plus ()
+ {
+ var x = (nint)10;
+ var z = +x;
+ if ((int)z != 10)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_neg ()
+ {
+ var x = (nint)10;
+ var z = -x;
+ if ((int)z != -10)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_comp ()
+ {
+ var x = (nint)10;
+ var z = ~x;
+ if ((int)z != ~10)
+ return 1;
+ return 0;
+ }
+
+#if FALSE
+ static int test_0_nint_inc ()
+ {
+ var x = (nint)10;
+ ++x;
+ if ((int)x != 11)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_dec ()
+ {
+ var x = (nint)10;
+ --x;
+ if ((int)x != 9)
+ return 1;
+ return 0;
+ }
+#endif
+
+ static int test_0_nint_add ()
+ {
+ var x = (nint)10;
+ var y = (nint)20;
+ var z = x + y;
+ if ((int)z != 30)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_sub ()
+ {
+ var x = (nint)10;
+ var y = (nint)20;
+ var z = x - y;
+ if ((int)z != -10)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_mul ()
+ {
+ var x = (nint)10;
+ var y = (nint)20;
+ var z = x * y;
+ if ((int)z != 200)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_div ()
+ {
+ var x = (nint)30;
+ var y = (nint)3;
+ var z = x / y;
+ if ((int)z != 10)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_rem ()
+ {
+ var x = (nint)22;
+ var y = (nint)10;
+ var z = x % y;
+ if ((int)z != 2)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_and ()
+ {
+ var x = (nint)0x30;
+ var y = (nint)0x11;
+ var z = x & y;
+ if ((int)z != 0x10)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_or ()
+ {
+ var x = (nint)0x0F;
+ var y = (nint)0xF0;
+ var z = x | y;
+ if ((int)z != 0xFF)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_xor ()
+ {
+ var x = (nint)0xFF;
+ var y = (nint)0xF0;
+ var z = x ^ y;
+ if ((int)z != 0x0F)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_shl ()
+ {
+ var x = (nint)10;
+ var z = x << 2;
+ if ((int)z != 40)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_shr ()
+ {
+ var x = (nint)10;
+ var z = x >> 2;
+ if ((int)z != 2)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nint_cmp_same_val ()
+ {
+ var x = (nint)10;
+ var y = (nint)10;
+ if (!(x == y))
+ return 1;
+ if (x != y)
+ return 2;
+ if (x < y)
+ return 3;
+ if (x > y)
+ return 4;
+ if (!(x <= y))
+ return 5;
+ if (!(x >= y))
+ return 6;
+ return 0;
+ }
+
+ static int test_0_nint_cmp_small_val ()
+ {
+ var x = (nint)5;
+ var y = (nint)10;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (!(x < y))
+ return 3;
+ if (x > y)
+ return 4;
+ if (!(x <= y))
+ return 5;
+ if (x >= y)
+ return 6;
+ return 0;
+ }
+
+ static int test_0_nint_cmp_large_val ()
+ {
+ var x = (nint)20;
+ var y = (nint)10;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (x < y)
+ return 3;
+ if (!(x > y))
+ return 4;
+ if (x <= y)
+ return 1;
+ if (!(x >= y))
+ return 1;
+ return 0;
+ }
+
+ // static int test_0_nint_call_boxed_equals ()
+ // {
+ // object x = new nint (10);
+ // object y = new nint (10);
+ // if (!x.Equals (y))
+ // return 1;
+ // return 0;
+ // }
+
+ static int test_0_nint_call_boxed_funs ()
+ {
+ object x = new nint (10);
+ object y = new nint (10);
+ if (x.GetHashCode () == 0)
+ return 2;
+ if (x.ToString () != "10")
+ return 3;
+ return 0;
+ }
+
+ public int test_0_nint_unboxed_member_calls ()
+ {
+ var x = (nint)10;
+#if FALSE
+ if (!x.Equals (x))
+ return 1;
+#endif
+ if (x != nint.Parse ("10"))
+ return 2;
+ return 0;
+ }
+
+ static int test_0_nuint_ctor ()
+ {
+ var x = new nuint (10u);
+ var y = new nuint (x);
+ var z = new nuint (new nuint (20u));
+ if ((uint)x != 10)
+ return 1;
+ if ((uint)y != 10)
+ return 2;
+ if ((uint)z != 20)
+ return 3;
+ return 0;
+ }
+
+ static int test_0_nuint_casts ()
+ {
+ var x = (nuint)10;
+ var y = (nuint)20L;
+
+ if ((uint)x != 10)
+ return 1;
+ if ((ulong)x != 10L)
+ return 2;
+ if ((uint)y != 20)
+ return 3;
+ if ((ulong)y != 20L)
+ return 4;
+ return 0;
+ }
+
+ static int test_0_nuint_plus ()
+ {
+ var x = (nuint)10;
+ var z = +x;
+ if ((uint)z != 10)
+ return 1;
+ return 0;
+ }
+
+ // static int test_0_nuint_neg ()
+ // {
+ // var x = (nuint)10;
+ // var z = -x;
+ // if ((uint)z != -10)
+ // return 1;
+ // return 0;
+ // }
+
+ static int test_0_nuint_comp ()
+ {
+ var x = (nuint)10;
+ var z = ~x;
+ if ((uint)z != ~10u)
+ return 1;
+ return 0;
+ }
+
+#if FALSE
+ static int test_0_nuint_inc ()
+ {
+ var x = (nuint)10;
+ ++x;
+ if ((uint)x != 11)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_dec ()
+ {
+ var x = (nuint)10;
+ --x;
+ if ((uint)x != 9)
+ return 1;
+ return 0;
+ }
+#endif
+
+ static int test_0_nuint_add ()
+ {
+ var x = (nuint)10;
+ var y = (nuint)20;
+ var z = x + y;
+ if ((uint)z != 30)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_sub ()
+ {
+ var x = (nuint)20;
+ var y = (nuint)5;
+ var z = x - y;
+ if ((uint)z != 15)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_mul ()
+ {
+ var x = (nuint)10;
+ var y = (nuint)20;
+ var z = x * y;
+ if ((uint)z != 200)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_div ()
+ {
+ var x = (nuint)30;
+ var y = (nuint)3;
+ var z = x / y;
+ if ((uint)z != 10)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_rem ()
+ {
+ var x = (nuint)22;
+ var y = (nuint)10;
+ var z = x % y;
+ if ((uint)z != 2)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_and ()
+ {
+ var x = (nuint)0x30;
+ var y = (nuint)0x11;
+ var z = x & y;
+ if ((uint)z != 0x10)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_or ()
+ {
+ var x = (nuint)0x0F;
+ var y = (nuint)0xF0;
+ var z = x | y;
+ if ((uint)z != 0xFF)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_xor ()
+ {
+ var x = (nuint)0xFF;
+ var y = (nuint)0xF0;
+ var z = x ^ y;
+ if ((uint)z != 0x0F)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_shl ()
+ {
+ var x = (nuint)10;
+ var z = x << 2;
+ if ((uint)z != 40)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_shr ()
+ {
+ var x = (nuint)10;
+ var z = x >> 2;
+ if ((uint)z != 2)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nuint_cmp_same_val ()
+ {
+ var x = (nuint)10;
+ var y = (nuint)10;
+ if (!(x == y))
+ return 1;
+ if (x != y)
+ return 2;
+ if (x < y)
+ return 3;
+ if (x > y)
+ return 4;
+ if (!(x <= y))
+ return 5;
+ if (!(x >= y))
+ return 6;
+ return 0;
+ }
+
+ static int test_0_nuint_cmp_small_val ()
+ {
+ var x = (nuint)5;
+ var y = (nuint)10;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (!(x < y))
+ return 3;
+ if (x > y)
+ return 4;
+ if (!(x <= y))
+ return 5;
+ if (x >= y)
+ return 6;
+ return 0;
+ }
+
+ static int test_0_nuint_cmp_large_val ()
+ {
+ var x = (nuint)20;
+ var y = (nuint)10;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (x < y)
+ return 3;
+ if (!(x > y))
+ return 4;
+ if (x <= y)
+ return 1;
+ if (!(x >= y))
+ return 1;
+ return 0;
+ }
+
+ // static int test_0_nuint_call_boxed_equals ()
+ // {
+ // object x = new nuint (10);
+ // object y = new nuint (10);
+ // if (!x.Equals (y))
+ // return 1;
+ // return 0;
+ // }
+
+ static int test_0_nuint_call_boxed_funs ()
+ {
+ object x = new nuint (10u);
+ object y = new nuint (10u);
+ if (x.GetHashCode () == 0)
+ return 2;
+ if (x.ToString () != "10")
+ return 3;
+ return 0;
+ }
+
+ public int test_0_nuint_unboxed_member_calls ()
+ {
+ var x = (nuint)10;
+#if FALSE
+ if (!x.Equals (x))
+ return 1;
+#endif
+ if (x != nuint.Parse ("10"))
+ return 2;
+ return 0;
+ }
+
+ static int test_0_nfloat_ctor ()
+ {
+ var x = new nfloat (10.0f);
+ var y = new nfloat (x);
+ var z = new nfloat (new nfloat (20f));
+ if ((float)x != 10f)
+ return 1;
+ if ((float)y != 10f)
+ return 2;
+ if ((float)z != 20f)
+ return 3;
+ return 0;
+ }
+
+ static int test_0_nfloat_casts ()
+ {
+ var x = (nfloat)10f;
+
+ if ((float)x != 10f)
+ return 1;
+ if ((double)x != 10)
+ return 2;
+#if FALSE
+ var y = (nfloat)20;
+ if ((float)y != 20f)
+ return 3;
+ if ((double)y != 20)
+ return 4;
+#endif
+ return 0;
+ }
+
+ static int test_0_nfloat_plus ()
+ {
+ var x = (nfloat)10f;
+ var z = +x;
+ if ((float)z != 10f)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nfloat_neg ()
+ {
+ var x = (nfloat)10f;
+ var z = -x;
+ if ((float)z != -10f)
+ return 1;
+ return 0;
+ }
+
+#if FALSE
+ static int test_0_nfloat_inc ()
+ {
+ var x = (nfloat)10f;
+ ++x;
+ if ((float)x != 11f) {
+ Console.WriteLine ((float)x);
+ return 1;
+ }
+ return 0;
+ }
+
+ static int test_0_nfloat_dec ()
+ {
+ var x = (nfloat)10f;
+ --x;
+ if ((float)x != 9f) {
+ Console.WriteLine ((float)x);
+ return 1;
+ }
+ return 0;
+ }
+#endif
+
+ static int test_0_nfloat_add ()
+ {
+ var x = (nfloat)10f;
+ var y = (nfloat)20f;
+ var z = x + y;
+ if ((float)z != 30f)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nfloat_sub ()
+ {
+ var x = (nfloat)10f;
+ var y = (nfloat)20f;
+ var z = x - y;
+ if ((float)z != -10f)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nfloat_mul ()
+ {
+ var x = (nfloat)10f;
+ var y = (nfloat)20f;
+ var z = x * y;
+ if ((float)z != 200f)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nfloat_div ()
+ {
+ var x = (nfloat)30f;
+ var y = (nfloat)3f;
+ var z = x / y;
+ if ((float)z != 10f)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nfloat_rem ()
+ {
+ var x = (nfloat)22f;
+ var y = (nfloat)10f;
+ var z = x % y;
+ if ((float)z != 2f)
+ return 1;
+ return 0;
+ }
+
+ static int test_0_nfloat_cmp_same_val ()
+ {
+ var x = (nfloat)10f;
+ var y = (nfloat)10f;
+ if (!(x == y))
+ return 1;
+ if (x != y)
+ return 2;
+ if (x < y)
+ return 3;
+ if (x > y)
+ return 4;
+ if (!(x <= y))
+ return 5;
+ if (!(x >= y))
+ return 6;
+ return 0;
+ }
+
+ static int test_0_nfloat_cmp_small_val ()
+ {
+ var x = (nfloat)5f;
+ var y = (nfloat)10f;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (!(x < y))
+ return 3;
+ if (x > y)
+ return 4;
+ if (!(x <= y))
+ return 5;
+ if (x >= y)
+ return 6;
+ return 0;
+ }
+
+ static int test_0_nfloat_cmp_large_val ()
+ {
+ var x = (nfloat)20f;
+ var y = (nfloat)10f;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (x < y)
+ return 3;
+ if (!(x > y))
+ return 4;
+ if (x <= y)
+ return 1;
+ if (!(x >= y))
+ return 1;
+ return 0;
+ }
+
+ /* fails on arm64 */
+#if FALSE
+ static int test_0_nfloat_cmp_left_nan ()
+ {
+ var x = (nfloat)float.NaN;
+ var y = (nfloat)10f;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (x < y)
+ return 3;
+ if (x > y)
+ return 4;
+ if (x <= y)
+ return 1;
+ if (x >= y)
+ return 1;
+ return 0;
+ }
+
+
+ static int test_0_nfloat_cmp_right_nan ()
+ {
+ var x = (nfloat)10f;
+ var y = (nfloat)float.NaN;
+ if (x == y)
+ return 1;
+ if (!(x != y))
+ return 2;
+ if (x < y)
+ return 3;
+ if (x > y)
+ return 4;
+ if (x <= y)
+ return 1;
+ if (x >= y)
+ return 1;
+ return 0;
+ }
+#endif
+
+ // static int test_0_nfloat_call_boxed_equals ()
+ // {
+ // object x = new nfloat (10f);
+ // object y = new nfloat (10f);
+ // if (!x.Equals (y))
+ // return 1;
+ // return 0;
+ // }
+
+ static int test_0_nfloat_call_boxed_funs ()
+ {
+ object x = new nfloat (10f);
+ object y = new nfloat (10f);
+ if (x.GetHashCode () == 0)
+ return 2;
+ if (x.ToString () != "10")
+ return 3;
+ return 0;
+ }
+
+ public int test_0_nfloat_unboxed_member_calls ()
+ {
+ var x = (nfloat)10f;
+#if FALSE
+ if (!x.Equals (x))
+ return 1;
+#endif
+ if (x != nfloat.Parse ("10"))
+ return 2;
+ return 0;
+ }
+
+ public static int Main (String[] args) {
+ return TestDriver.RunTests (typeof (BuiltinTests), args);
+ }
+}
+
+
+// !!! WARNING - GENERATED CODE - DO NOT EDIT !!!
+//
+// Generated by NativeTypes.tt, a T4 template.
+//
+// NativeTypes.cs: basic types with 32 or 64 bit sizes:
+//
+// - nint
+// - nuint
+// - nfloat
+//
+// Authors:
+// Aaron Bockover <abock@xamarin.com>
+//
+// Copyright 2013 Xamarin, Inc. All rights reserved.
+//
+
+namespace System
+{
+ [Serializable]
+ [DebuggerDisplay ("{v,nq}")]
+ public unsafe struct nint : IFormattable, IConvertible, IComparable, IComparable<nint>, IEquatable <nint>
+ {
+ internal nint (nint v) { this.v = v.v; }
+ public nint (Int32 v) { this.v = v; }
+
+#if ARCH_32
+ public static readonly int Size = 4;
+
+ public static readonly nint MaxValue = Int32.MaxValue;
+ public static readonly nint MinValue = Int32.MinValue;
+
+ [DebuggerBrowsable (DebuggerBrowsableState.Never)]
+ internal Int32 v;
+
+ public nint (Int64 v) { this.v = (Int32)v; }
+#else
+ public static readonly int Size = 8;
+
+ public static readonly nint MaxValue = (nint) Int64.MaxValue; // 64-bit only codepath
+ public static readonly nint MinValue = (nint) Int64.MinValue; // 64-bit only codepath
+
+ [DebuggerBrowsable (DebuggerBrowsableState.Never)]
+ internal Int64 v;
+
+ public nint (Int64 v) { this.v = v; }
+#endif
+
+ public static explicit operator nint (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v.v);
+#else
+ return new nint ((long)v.v);
+#endif
+ }
+
+ public static explicit operator nuint (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v.v);
+#else
+ return new nuint ((ulong)v.v);
+#endif
+ }
+
+ public static explicit operator nint (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v.v);
+#else
+ return new nint ((long)v.v);
+#endif
+ }
+
+ public static implicit operator nfloat (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v.v);
+#else
+ return new nfloat ((double)v.v);
+#endif
+ }
+
+ public static explicit operator nint (IntPtr v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint (*((int *)&v));
+#else
+ return new nint (*((long *)&v));
+#endif
+ }
+
+ public static explicit operator IntPtr (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return *((IntPtr *)&v.v);
+#else
+ return *((IntPtr *)&v.v);
+#endif
+ }
+
+ public static implicit operator nint (sbyte v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator sbyte (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (sbyte)v.v;
+#else
+ return (sbyte)v.v;
+#endif
+ }
+
+ public static implicit operator nint (byte v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator byte (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (byte)v.v;
+#else
+ return (byte)v.v;
+#endif
+ }
+
+ public static implicit operator nint (char v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator char (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (char)v.v;
+#else
+ return (char)v.v;
+#endif
+ }
+
+ public static implicit operator nint (short v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator short (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (short)v.v;
+#else
+ return (short)v.v;
+#endif
+ }
+
+ public static explicit operator nint (ushort v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator ushort (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (ushort)v.v;
+#else
+ return (ushort)v.v;
+#endif
+ }
+
+ public static implicit operator nint (int v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator int (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (int)v.v;
+#else
+ return (int)v.v;
+#endif
+ }
+
+ public static explicit operator nint (uint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator uint (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (uint)v.v;
+#else
+ return (uint)v.v;
+#endif
+ }
+
+ public static explicit operator nint (long v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static implicit operator long (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (long)v.v;
+#else
+ return (long)v.v;
+#endif
+ }
+
+ public static explicit operator nint (ulong v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static explicit operator ulong (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (ulong)v.v;
+#else
+ return (ulong)v.v;
+#endif
+ }
+
+ public static explicit operator nint (float v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static implicit operator float (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (float)v.v;
+#else
+ return (float)v.v;
+#endif
+ }
+
+ public static explicit operator nint (double v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static implicit operator double (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (double)v.v;
+#else
+ return (double)v.v;
+#endif
+ }
+
+ public static explicit operator nint (decimal v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nint ((int)v);
+#else
+ return new nint ((long)v);
+#endif
+ }
+
+ public static implicit operator decimal (nint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (decimal)v.v;
+#else
+ return (decimal)v.v;
+#endif
+ }
+
+#if NINT_JIT_OPTIMIZED
+ public static nint operator + (nint v) { throw new NotImplementedException (); }
+ public static nint operator - (nint v) { throw new NotImplementedException (); }
+ public static nint operator ~ (nint v) { throw new NotImplementedException (); }
+#else
+ public static nint operator + (nint v) { return new nint (+v.v); }
+ public static nint operator - (nint v) { return new nint (-v.v); }
+ public static nint operator ~ (nint v) { return new nint (~v.v); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static nint operator ++ (nint v) { throw new NotImplementedException (); }
+ public static nint operator -- (nint v) { throw new NotImplementedException (); }
+#else
+ public static nint operator ++ (nint v) { return new nint (v.v + 1); }
+ public static nint operator -- (nint v) { return new nint (v.v - 1); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static nint operator + (nint l, nint r) { throw new NotImplementedException (); }
+ public static nint operator - (nint l, nint r) { throw new NotImplementedException (); }
+ public static nint operator * (nint l, nint r) { throw new NotImplementedException (); }
+ public static nint operator / (nint l, nint r) { throw new NotImplementedException (); }
+ public static nint operator % (nint l, nint r) { throw new NotImplementedException (); }
+ public static nint operator & (nint l, nint r) { throw new NotImplementedException (); }
+ public static nint operator | (nint l, nint r) { throw new NotImplementedException (); }
+ public static nint operator ^ (nint l, nint r) { throw new NotImplementedException (); }
+
+ public static nint operator << (nint l, int r) { throw new NotImplementedException (); }
+ public static nint operator >> (nint l, int r) { throw new NotImplementedException (); }
+#else
+ public static nint operator + (nint l, nint r) { return new nint (l.v + r.v); }
+ public static nint operator - (nint l, nint r) { return new nint (l.v - r.v); }
+ public static nint operator * (nint l, nint r) { return new nint (l.v * r.v); }
+ public static nint operator / (nint l, nint r) { return new nint (l.v / r.v); }
+ public static nint operator % (nint l, nint r) { return new nint (l.v % r.v); }
+ public static nint operator & (nint l, nint r) { return new nint (l.v & r.v); }
+ public static nint operator | (nint l, nint r) { return new nint (l.v | r.v); }
+ public static nint operator ^ (nint l, nint r) { return new nint (l.v ^ r.v); }
+
+ public static nint operator << (nint l, int r) { return new nint (l.v << r); }
+ public static nint operator >> (nint l, int r) { return new nint (l.v >> r); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static bool operator == (nint l, nint r) { throw new NotImplementedException (); }
+ public static bool operator != (nint l, nint r) { throw new NotImplementedException (); }
+ public static bool operator < (nint l, nint r) { throw new NotImplementedException (); }
+ public static bool operator > (nint l, nint r) { throw new NotImplementedException (); }
+ public static bool operator <= (nint l, nint r) { throw new NotImplementedException (); }
+ public static bool operator >= (nint l, nint r) { throw new NotImplementedException (); }
+#else
+ public static bool operator == (nint l, nint r) { return l.v == r.v; }
+ public static bool operator != (nint l, nint r) { return l.v != r.v; }
+ public static bool operator < (nint l, nint r) { return l.v < r.v; }
+ public static bool operator > (nint l, nint r) { return l.v > r.v; }
+ public static bool operator <= (nint l, nint r) { return l.v <= r.v; }
+ public static bool operator >= (nint l, nint r) { return l.v >= r.v; }
+#endif
+
+ public int CompareTo (nint value) { return v.CompareTo (value.v); }
+ public int CompareTo (object value)
+ {
+ if (value is nint)
+ return v.CompareTo (((nint) value).v);
+ return v.CompareTo (value);
+ }
+ public bool Equals (nint obj) { return v.Equals (obj.v); }
+ public override bool Equals (object obj)
+ {
+ if (obj is nint)
+ return v.Equals (((nint) obj).v);
+ return v.Equals (obj);
+ }
+ public override int GetHashCode () { return v.GetHashCode (); }
+
+#if ARCH_32
+ public static nint Parse (string s, IFormatProvider provider) { return (nint)Int32.Parse (s, provider); }
+ public static nint Parse (string s, NumberStyles style) { return (nint)Int32.Parse (s, style); }
+ public static nint Parse (string s) { return (nint)Int32.Parse (s); }
+ public static nint Parse (string s, NumberStyles style, IFormatProvider provider) {
+ return (nint)Int32.Parse (s, style, provider);
+ }
+
+ public static bool TryParse (string s, out nint result)
+ {
+ Int32 v;
+ var r = Int32.TryParse (s, out v);
+ result = (nint)v;
+ return r;
+ }
+
+ public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out nint result)
+ {
+ Int32 v;
+ var r = Int32.TryParse (s, style, provider, out v);
+ result = (nint)v;
+ return r;
+ }
+#else
+ public static nint Parse (string s, IFormatProvider provider) { return (nint)Int64.Parse (s, provider); }
+ public static nint Parse (string s, NumberStyles style) { return (nint)Int64.Parse (s, style); }
+ public static nint Parse (string s) { return (nint)Int64.Parse (s); }
+ public static nint Parse (string s, NumberStyles style, IFormatProvider provider) {
+ return (nint)Int64.Parse (s, style, provider);
+ }
+
+ public static bool TryParse (string s, out nint result)
+ {
+ Int64 v;
+ var r = Int64.TryParse (s, out v);
+ result = (nint)v;
+ return r;
+ }
+
+ public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out nint result)
+ {
+ Int64 v;
+ var r = Int64.TryParse (s, style, provider, out v);
+ result = (nint)v;
+ return r;
+ }
+#endif
+
+ public override string ToString () { return v.ToString (); }
+ public string ToString (IFormatProvider provider) { return v.ToString (provider); }
+ public string ToString (string format) { return v.ToString (format); }
+ public string ToString (string format, IFormatProvider provider) { return v.ToString (format, provider); }
+
+ public TypeCode GetTypeCode () { return v.GetTypeCode (); }
+
+ bool IConvertible.ToBoolean (IFormatProvider provider) { return ((IConvertible)v).ToBoolean (provider); }
+ byte IConvertible.ToByte (IFormatProvider provider) { return ((IConvertible)v).ToByte (provider); }
+ char IConvertible.ToChar (IFormatProvider provider) { return ((IConvertible)v).ToChar (provider); }
+ DateTime IConvertible.ToDateTime (IFormatProvider provider) { return ((IConvertible)v).ToDateTime (provider); }
+ decimal IConvertible.ToDecimal (IFormatProvider provider) { return ((IConvertible)v).ToDecimal (provider); }
+ double IConvertible.ToDouble (IFormatProvider provider) { return ((IConvertible)v).ToDouble (provider); }
+ short IConvertible.ToInt16 (IFormatProvider provider) { return ((IConvertible)v).ToInt16 (provider); }
+ int IConvertible.ToInt32 (IFormatProvider provider) { return ((IConvertible)v).ToInt32 (provider); }
+ long IConvertible.ToInt64 (IFormatProvider provider) { return ((IConvertible)v).ToInt64 (provider); }
+ sbyte IConvertible.ToSByte (IFormatProvider provider) { return ((IConvertible)v).ToSByte (provider); }
+ float IConvertible.ToSingle (IFormatProvider provider) { return ((IConvertible)v).ToSingle (provider); }
+ ushort IConvertible.ToUInt16 (IFormatProvider provider) { return ((IConvertible)v).ToUInt16 (provider); }
+ uint IConvertible.ToUInt32 (IFormatProvider provider) { return ((IConvertible)v).ToUInt32 (provider); }
+ ulong IConvertible.ToUInt64 (IFormatProvider provider) { return ((IConvertible)v).ToUInt64 (provider); }
+
+ object IConvertible.ToType (Type targetType, IFormatProvider provider) {
+ return ((IConvertible)v).ToType (targetType, provider);
+ }
+
+ public static void CopyArray (IntPtr source, nint [] destination, int startIndex, int length)
+ {
+ if (source == IntPtr.Zero)
+ throw new ArgumentNullException ("source");
+ if (destination == null)
+ throw new ArgumentNullException ("destination");
+ if (destination.Rank != 1)
+ throw new ArgumentException ("destination", "array is multi-dimensional");
+ if (startIndex < 0)
+ throw new ArgumentException ("startIndex", "must be >= 0");
+ if (length < 0)
+ throw new ArgumentException ("length", "must be >= 0");
+ if (startIndex + length > destination.Length)
+ throw new ArgumentException ("length", "startIndex + length > destination.Length");
+
+ for (int i = 0; i < length; i++)
+ destination [i + startIndex] = (nint)Marshal.ReadIntPtr (source, i * nint.Size);
+ }
+
+ public static void CopyArray (nint [] source, int startIndex, IntPtr destination, int length)
+ {
+ if (source == null)
+ throw new ArgumentNullException ("source");
+ if (destination == IntPtr.Zero)
+ throw new ArgumentNullException ("destination");
+ if (source.Rank != 1)
+ throw new ArgumentException ("source", "array is multi-dimensional");
+ if (startIndex < 0)
+ throw new ArgumentException ("startIndex", "must be >= 0");
+ if (length < 0)
+ throw new ArgumentException ("length", "must be >= 0");
+ if (startIndex + length > source.Length)
+ throw new ArgumentException ("length", "startIndex + length > source.Length");
+
+ for (int i = 0; i < length; i++)
+ Marshal.WriteIntPtr (destination, i * nint.Size, (IntPtr)source [i + startIndex]);
+ }
+ }
+ [Serializable]
+ [DebuggerDisplay ("{v,nq}")]
+ public unsafe struct nuint : IFormattable, IConvertible, IComparable, IComparable<nuint>, IEquatable <nuint>
+ {
+ internal nuint (nuint v) { this.v = v.v; }
+ public nuint (UInt32 v) { this.v = v; }
+
+#if ARCH_32
+ public static readonly int Size = 4;
+
+ public static readonly nuint MaxValue = UInt32.MaxValue;
+ public static readonly nuint MinValue = UInt32.MinValue;
+
+ [DebuggerBrowsable (DebuggerBrowsableState.Never)]
+ internal UInt32 v;
+
+ public nuint (UInt64 v) { this.v = (UInt32)v; }
+#else
+ public static readonly int Size = 8;
+
+ public static readonly nuint MaxValue = (nuint) UInt64.MaxValue; // 64-bit only codepath
+ public static readonly nuint MinValue = (nuint) UInt64.MinValue; // 64-bit only codepath
+
+ [DebuggerBrowsable (DebuggerBrowsableState.Never)]
+ internal UInt64 v;
+
+ public nuint (UInt64 v) { this.v = v; }
+#endif
+
+ public static explicit operator nuint (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v.v);
+#else
+ return new nuint ((ulong)v.v);
+#endif
+ }
+
+ public static implicit operator nfloat (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v.v);
+#else
+ return new nfloat ((double)v.v);
+#endif
+ }
+
+ public static explicit operator nuint (IntPtr v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint (*((uint *)&v));
+#else
+ return new nuint (*((ulong *)&v));
+#endif
+ }
+
+ public static explicit operator IntPtr (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return *((IntPtr *)&v.v);
+#else
+ return *((IntPtr *)&v.v);
+#endif
+ }
+
+ public static explicit operator nuint (sbyte v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator sbyte (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (sbyte)v.v;
+#else
+ return (sbyte)v.v;
+#endif
+ }
+
+ public static implicit operator nuint (byte v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator byte (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (byte)v.v;
+#else
+ return (byte)v.v;
+#endif
+ }
+
+ public static implicit operator nuint (char v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator char (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (char)v.v;
+#else
+ return (char)v.v;
+#endif
+ }
+
+ public static explicit operator nuint (short v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator short (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (short)v.v;
+#else
+ return (short)v.v;
+#endif
+ }
+
+ public static implicit operator nuint (ushort v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator ushort (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (ushort)v.v;
+#else
+ return (ushort)v.v;
+#endif
+ }
+
+ public static explicit operator nuint (int v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator int (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (int)v.v;
+#else
+ return (int)v.v;
+#endif
+ }
+
+ public static implicit operator nuint (uint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator uint (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (uint)v.v;
+#else
+ return (uint)v.v;
+#endif
+ }
+
+ public static explicit operator nuint (long v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static explicit operator long (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (long)v.v;
+#else
+ return (long)v.v;
+#endif
+ }
+
+ public static explicit operator nuint (ulong v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static implicit operator ulong (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (ulong)v.v;
+#else
+ return (ulong)v.v;
+#endif
+ }
+
+ public static explicit operator nuint (float v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static implicit operator float (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (float)v.v;
+#else
+ return (float)v.v;
+#endif
+ }
+
+ public static explicit operator nuint (double v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static implicit operator double (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (double)v.v;
+#else
+ return (double)v.v;
+#endif
+ }
+
+ public static explicit operator nuint (decimal v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nuint ((uint)v);
+#else
+ return new nuint ((ulong)v);
+#endif
+ }
+
+ public static implicit operator decimal (nuint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (decimal)v.v;
+#else
+ return (decimal)v.v;
+#endif
+ }
+
+#if NINT_JIT_OPTIMIZED
+ public static nuint operator + (nuint v) { throw new NotImplementedException (); }
+ public static nuint operator ~ (nuint v) { throw new NotImplementedException (); }
+#else
+ public static nuint operator + (nuint v) { return new nuint (+v.v); }
+ public static nuint operator ~ (nuint v) { return new nuint (~v.v); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static nuint operator ++ (nuint v) { throw new NotImplementedException (); }
+ public static nuint operator -- (nuint v) { throw new NotImplementedException (); }
+#else
+ public static nuint operator ++ (nuint v) { return new nuint (v.v + 1); }
+ public static nuint operator -- (nuint v) { return new nuint (v.v - 1); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static nuint operator + (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static nuint operator - (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static nuint operator * (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static nuint operator / (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static nuint operator % (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static nuint operator & (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static nuint operator | (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static nuint operator ^ (nuint l, nuint r) { throw new NotImplementedException (); }
+
+ public static nuint operator << (nuint l, int r) { throw new NotImplementedException (); }
+ public static nuint operator >> (nuint l, int r) { throw new NotImplementedException (); }
+#else
+ public static nuint operator + (nuint l, nuint r) { return new nuint (l.v + r.v); }
+ public static nuint operator - (nuint l, nuint r) { return new nuint (l.v - r.v); }
+ public static nuint operator * (nuint l, nuint r) { return new nuint (l.v * r.v); }
+ public static nuint operator / (nuint l, nuint r) { return new nuint (l.v / r.v); }
+ public static nuint operator % (nuint l, nuint r) { return new nuint (l.v % r.v); }
+ public static nuint operator & (nuint l, nuint r) { return new nuint (l.v & r.v); }
+ public static nuint operator | (nuint l, nuint r) { return new nuint (l.v | r.v); }
+ public static nuint operator ^ (nuint l, nuint r) { return new nuint (l.v ^ r.v); }
+
+ public static nuint operator << (nuint l, int r) { return new nuint (l.v << r); }
+ public static nuint operator >> (nuint l, int r) { return new nuint (l.v >> r); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static bool operator == (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static bool operator != (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static bool operator < (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static bool operator > (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static bool operator <= (nuint l, nuint r) { throw new NotImplementedException (); }
+ public static bool operator >= (nuint l, nuint r) { throw new NotImplementedException (); }
+#else
+ public static bool operator == (nuint l, nuint r) { return l.v == r.v; }
+ public static bool operator != (nuint l, nuint r) { return l.v != r.v; }
+ public static bool operator < (nuint l, nuint r) { return l.v < r.v; }
+ public static bool operator > (nuint l, nuint r) { return l.v > r.v; }
+ public static bool operator <= (nuint l, nuint r) { return l.v <= r.v; }
+ public static bool operator >= (nuint l, nuint r) { return l.v >= r.v; }
+#endif
+
+ public int CompareTo (nuint value) { return v.CompareTo (value.v); }
+ public int CompareTo (object value)
+ {
+ if (value is nuint)
+ return v.CompareTo (((nuint) value).v);
+ return v.CompareTo (value);
+ }
+ public bool Equals (nuint obj) { return v.Equals (obj.v); }
+ public override bool Equals (object obj)
+ {
+ if (obj is nuint)
+ return v.Equals (((nuint) obj).v);
+ return v.Equals (obj);
+ }
+ public override int GetHashCode () { return v.GetHashCode (); }
+
+#if ARCH_32
+ public static nuint Parse (string s, IFormatProvider provider) { return (nuint)UInt32.Parse (s, provider); }
+ public static nuint Parse (string s, NumberStyles style) { return (nuint)UInt32.Parse (s, style); }
+ public static nuint Parse (string s) { return (nuint)UInt32.Parse (s); }
+ public static nuint Parse (string s, NumberStyles style, IFormatProvider provider) {
+ return (nuint)UInt32.Parse (s, style, provider);
+ }
+
+ public static bool TryParse (string s, out nuint result)
+ {
+ UInt32 v;
+ var r = UInt32.TryParse (s, out v);
+ result = (nuint)v;
+ return r;
+ }
+
+ public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out nuint result)
+ {
+ UInt32 v;
+ var r = UInt32.TryParse (s, style, provider, out v);
+ result = (nuint)v;
+ return r;
+ }
+#else
+ public static nuint Parse (string s, IFormatProvider provider) { return (nuint)UInt64.Parse (s, provider); }
+ public static nuint Parse (string s, NumberStyles style) { return (nuint)UInt64.Parse (s, style); }
+ public static nuint Parse (string s) { return (nuint)UInt64.Parse (s); }
+ public static nuint Parse (string s, NumberStyles style, IFormatProvider provider) {
+ return (nuint)UInt64.Parse (s, style, provider);
+ }
+
+ public static bool TryParse (string s, out nuint result)
+ {
+ UInt64 v;
+ var r = UInt64.TryParse (s, out v);
+ result = (nuint)v;
+ return r;
+ }
+
+ public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out nuint result)
+ {
+ UInt64 v;
+ var r = UInt64.TryParse (s, style, provider, out v);
+ result = (nuint)v;
+ return r;
+ }
+#endif
+
+ public override string ToString () { return v.ToString (); }
+ public string ToString (IFormatProvider provider) { return v.ToString (provider); }
+ public string ToString (string format) { return v.ToString (format); }
+ public string ToString (string format, IFormatProvider provider) { return v.ToString (format, provider); }
+
+ public TypeCode GetTypeCode () { return v.GetTypeCode (); }
+
+ bool IConvertible.ToBoolean (IFormatProvider provider) { return ((IConvertible)v).ToBoolean (provider); }
+ byte IConvertible.ToByte (IFormatProvider provider) { return ((IConvertible)v).ToByte (provider); }
+ char IConvertible.ToChar (IFormatProvider provider) { return ((IConvertible)v).ToChar (provider); }
+ DateTime IConvertible.ToDateTime (IFormatProvider provider) { return ((IConvertible)v).ToDateTime (provider); }
+ decimal IConvertible.ToDecimal (IFormatProvider provider) { return ((IConvertible)v).ToDecimal (provider); }
+ double IConvertible.ToDouble (IFormatProvider provider) { return ((IConvertible)v).ToDouble (provider); }
+ short IConvertible.ToInt16 (IFormatProvider provider) { return ((IConvertible)v).ToInt16 (provider); }
+ int IConvertible.ToInt32 (IFormatProvider provider) { return ((IConvertible)v).ToInt32 (provider); }
+ long IConvertible.ToInt64 (IFormatProvider provider) { return ((IConvertible)v).ToInt64 (provider); }
+ sbyte IConvertible.ToSByte (IFormatProvider provider) { return ((IConvertible)v).ToSByte (provider); }
+ float IConvertible.ToSingle (IFormatProvider provider) { return ((IConvertible)v).ToSingle (provider); }
+ ushort IConvertible.ToUInt16 (IFormatProvider provider) { return ((IConvertible)v).ToUInt16 (provider); }
+ uint IConvertible.ToUInt32 (IFormatProvider provider) { return ((IConvertible)v).ToUInt32 (provider); }
+ ulong IConvertible.ToUInt64 (IFormatProvider provider) { return ((IConvertible)v).ToUInt64 (provider); }
+
+ object IConvertible.ToType (Type targetType, IFormatProvider provider) {
+ return ((IConvertible)v).ToType (targetType, provider);
+ }
+
+ public static void CopyArray (IntPtr source, nuint [] destination, int startIndex, int length)
+ {
+ if (source == IntPtr.Zero)
+ throw new ArgumentNullException ("source");
+ if (destination == null)
+ throw new ArgumentNullException ("destination");
+ if (destination.Rank != 1)
+ throw new ArgumentException ("destination", "array is multi-dimensional");
+ if (startIndex < 0)
+ throw new ArgumentException ("startIndex", "must be >= 0");
+ if (length < 0)
+ throw new ArgumentException ("length", "must be >= 0");
+ if (startIndex + length > destination.Length)
+ throw new ArgumentException ("length", "startIndex + length > destination.Length");
+
+ for (int i = 0; i < length; i++)
+ destination [i + startIndex] = (nuint)Marshal.ReadIntPtr (source, i * nuint.Size);
+ }
+
+ public static void CopyArray (nuint [] source, int startIndex, IntPtr destination, int length)
+ {
+ if (source == null)
+ throw new ArgumentNullException ("source");
+ if (destination == IntPtr.Zero)
+ throw new ArgumentNullException ("destination");
+ if (source.Rank != 1)
+ throw new ArgumentException ("source", "array is multi-dimensional");
+ if (startIndex < 0)
+ throw new ArgumentException ("startIndex", "must be >= 0");
+ if (length < 0)
+ throw new ArgumentException ("length", "must be >= 0");
+ if (startIndex + length > source.Length)
+ throw new ArgumentException ("length", "startIndex + length > source.Length");
+
+ for (int i = 0; i < length; i++)
+ Marshal.WriteIntPtr (destination, i * nuint.Size, (IntPtr)source [i + startIndex]);
+ }
+ }
+ [Serializable]
+ [DebuggerDisplay ("{v,nq}")]
+ public unsafe struct nfloat : IFormattable, IConvertible, IComparable, IComparable<nfloat>, IEquatable <nfloat>
+ {
+ internal nfloat (nfloat v) { this.v = v.v; }
+ public nfloat (Single v) { this.v = v; }
+
+#if ARCH_32
+ public static readonly int Size = 4;
+
+ public static readonly nfloat MaxValue = Single.MaxValue;
+ public static readonly nfloat MinValue = Single.MinValue;
+ public static readonly nfloat Epsilon = (nfloat)Single.Epsilon;
+ public static readonly nfloat NaN = (nfloat)Single.NaN;
+ public static readonly nfloat NegativeInfinity = (nfloat)Single.NegativeInfinity;
+ public static readonly nfloat PositiveInfinity = (nfloat)Single.PositiveInfinity;
+
+ [DebuggerBrowsable (DebuggerBrowsableState.Never)]
+ internal Single v;
+
+ public nfloat (Double v) { this.v = (Single)v; }
+#else
+ public static readonly int Size = 8;
+
+ public static readonly nfloat MaxValue = (nfloat) Double.MaxValue; // 64-bit only codepath
+ public static readonly nfloat MinValue = (nfloat) Double.MinValue; // 64-bit only codepath
+ public static readonly nfloat Epsilon = (nfloat)Double.Epsilon;
+ public static readonly nfloat NaN = (nfloat)Double.NaN;
+ public static readonly nfloat NegativeInfinity = (nfloat)Double.NegativeInfinity;
+ public static readonly nfloat PositiveInfinity = (nfloat)Double.PositiveInfinity;
+
+ [DebuggerBrowsable (DebuggerBrowsableState.Never)]
+ internal Double v;
+
+ public nfloat (Double v) { this.v = v; }
+#endif
+
+ public static explicit operator nfloat (IntPtr v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat (*((float *)&v));
+#else
+ return new nfloat (*((double *)&v));
+#endif
+ }
+
+ public static explicit operator IntPtr (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return *((IntPtr *)&v.v);
+#else
+ return *((IntPtr *)&v.v);
+#endif
+ }
+
+ public static implicit operator nfloat (sbyte v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator sbyte (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (sbyte)v.v;
+#else
+ return (sbyte)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (byte v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator byte (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (byte)v.v;
+#else
+ return (byte)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (char v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator char (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (char)v.v;
+#else
+ return (char)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (short v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator short (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (short)v.v;
+#else
+ return (short)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (ushort v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator ushort (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (ushort)v.v;
+#else
+ return (ushort)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (int v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator int (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (int)v.v;
+#else
+ return (int)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (uint v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator uint (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (uint)v.v;
+#else
+ return (uint)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (long v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator long (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (long)v.v;
+#else
+ return (long)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (ulong v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator ulong (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (ulong)v.v;
+#else
+ return (ulong)v.v;
+#endif
+ }
+
+ public static implicit operator nfloat (float v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator float (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (float)v.v;
+#else
+ return (float)v.v;
+#endif
+ }
+
+ public static explicit operator nfloat (double v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static implicit operator double (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (double)v.v;
+#else
+ return (double)v.v;
+#endif
+ }
+
+ public static explicit operator nfloat (decimal v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return new nfloat ((float)v);
+#else
+ return new nfloat ((double)v);
+#endif
+ }
+
+ public static explicit operator decimal (nfloat v)
+ {
+#if NINT_JIT_OPTIMIZED
+ throw new NotImplementedException ();
+#elif ARCH_32
+ return (decimal)v.v;
+#else
+ return (decimal)v.v;
+#endif
+ }
+
+#if NINT_JIT_OPTIMIZED
+ public static nfloat operator + (nfloat v) { throw new NotImplementedException (); }
+ public static nfloat operator - (nfloat v) { throw new NotImplementedException (); }
+#else
+ public static nfloat operator + (nfloat v) { return new nfloat (+v.v); }
+ public static nfloat operator - (nfloat v) { return new nfloat (-v.v); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static nfloat operator ++ (nfloat v) { throw new NotImplementedException (); }
+ public static nfloat operator -- (nfloat v) { throw new NotImplementedException (); }
+#else
+ public static nfloat operator ++ (nfloat v) { return new nfloat (v.v + 1); }
+ public static nfloat operator -- (nfloat v) { return new nfloat (v.v - 1); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static nfloat operator + (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static nfloat operator - (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static nfloat operator * (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static nfloat operator / (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static nfloat operator % (nfloat l, nfloat r) { throw new NotImplementedException (); }
+#else
+ public static nfloat operator + (nfloat l, nfloat r) { return new nfloat (l.v + r.v); }
+ public static nfloat operator - (nfloat l, nfloat r) { return new nfloat (l.v - r.v); }
+ public static nfloat operator * (nfloat l, nfloat r) { return new nfloat (l.v * r.v); }
+ public static nfloat operator / (nfloat l, nfloat r) { return new nfloat (l.v / r.v); }
+ public static nfloat operator % (nfloat l, nfloat r) { return new nfloat (l.v % r.v); }
+#endif
+
+#if NINT_JIT_OPTIMIZED
+ public static bool operator == (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static bool operator != (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static bool operator < (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static bool operator > (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static bool operator <= (nfloat l, nfloat r) { throw new NotImplementedException (); }
+ public static bool operator >= (nfloat l, nfloat r) { throw new NotImplementedException (); }
+#else
+ public static bool operator == (nfloat l, nfloat r) { return l.v == r.v; }
+ public static bool operator != (nfloat l, nfloat r) { return l.v != r.v; }
+ public static bool operator < (nfloat l, nfloat r) { return l.v < r.v; }
+ public static bool operator > (nfloat l, nfloat r) { return l.v > r.v; }
+ public static bool operator <= (nfloat l, nfloat r) { return l.v <= r.v; }
+ public static bool operator >= (nfloat l, nfloat r) { return l.v >= r.v; }
+#endif
+
+ public int CompareTo (nfloat value) { return v.CompareTo (value.v); }
+ public int CompareTo (object value)
+ {
+ if (value is nfloat)
+ return v.CompareTo (((nfloat) value).v);
+ return v.CompareTo (value);
+ }
+ public bool Equals (nfloat obj) { return v.Equals (obj.v); }
+ public override bool Equals (object obj)
+ {
+ if (obj is nfloat)
+ return v.Equals (((nfloat) obj).v);
+ return v.Equals (obj);
+ }
+ public override int GetHashCode () { return v.GetHashCode (); }
+
+#if ARCH_32
+ public static bool IsNaN (nfloat f) { return Single.IsNaN ((Single)f); }
+ public static bool IsInfinity (nfloat f) { return Single.IsInfinity ((Single)f); }
+ public static bool IsPositiveInfinity (nfloat f) { return Single.IsPositiveInfinity ((Single)f); }
+ public static bool IsNegativeInfinity (nfloat f) { return Single.IsNegativeInfinity ((Single)f); }
+
+ public static nfloat Parse (string s, IFormatProvider provider) { return (nfloat)Single.Parse (s, provider); }
+ public static nfloat Parse (string s, NumberStyles style) { return (nfloat)Single.Parse (s, style); }
+ public static nfloat Parse (string s) { return (nfloat)Single.Parse (s); }
+ public static nfloat Parse (string s, NumberStyles style, IFormatProvider provider) {
+ return (nfloat)Single.Parse (s, style, provider);
+ }
+
+ public static bool TryParse (string s, out nfloat result)
+ {
+ Single v;
+ var r = Single.TryParse (s, out v);
+ result = (nfloat)v;
+ return r;
+ }
+
+ public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out nfloat result)
+ {
+ Single v;
+ var r = Single.TryParse (s, style, provider, out v);
+ result = (nfloat)v;
+ return r;
+ }
+#else
+ public static bool IsNaN (nfloat f) { return Double.IsNaN ((Double)f); }
+ public static bool IsInfinity (nfloat f) { return Double.IsInfinity ((Double)f); }
+ public static bool IsPositiveInfinity (nfloat f) { return Double.IsPositiveInfinity ((Double)f); }
+ public static bool IsNegativeInfinity (nfloat f) { return Double.IsNegativeInfinity ((Double)f); }
+
+ public static nfloat Parse (string s, IFormatProvider provider) { return (nfloat)Double.Parse (s, provider); }
+ public static nfloat Parse (string s, NumberStyles style) { return (nfloat)Double.Parse (s, style); }
+ public static nfloat Parse (string s) { return (nfloat)Double.Parse (s); }
+ public static nfloat Parse (string s, NumberStyles style, IFormatProvider provider) {
+ return (nfloat)Double.Parse (s, style, provider);
+ }
+
+ public static bool TryParse (string s, out nfloat result)
+ {
+ Double v;
+ var r = Double.TryParse (s, out v);
+ result = (nfloat)v;
+ return r;
+ }
+
+ public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out nfloat result)
+ {
+ Double v;
+ var r = Double.TryParse (s, style, provider, out v);
+ result = (nfloat)v;
+ return r;
+ }
+#endif
+
+ public override string ToString () { return v.ToString (); }
+ public string ToString (IFormatProvider provider) { return v.ToString (provider); }
+ public string ToString (string format) { return v.ToString (format); }
+ public string ToString (string format, IFormatProvider provider) { return v.ToString (format, provider); }
+
+ public TypeCode GetTypeCode () { return v.GetTypeCode (); }
+
+ bool IConvertible.ToBoolean (IFormatProvider provider) { return ((IConvertible)v).ToBoolean (provider); }
+ byte IConvertible.ToByte (IFormatProvider provider) { return ((IConvertible)v).ToByte (provider); }
+ char IConvertible.ToChar (IFormatProvider provider) { return ((IConvertible)v).ToChar (provider); }
+ DateTime IConvertible.ToDateTime (IFormatProvider provider) { return ((IConvertible)v).ToDateTime (provider); }
+ decimal IConvertible.ToDecimal (IFormatProvider provider) { return ((IConvertible)v).ToDecimal (provider); }
+ double IConvertible.ToDouble (IFormatProvider provider) { return ((IConvertible)v).ToDouble (provider); }
+ short IConvertible.ToInt16 (IFormatProvider provider) { return ((IConvertible)v).ToInt16 (provider); }
+ int IConvertible.ToInt32 (IFormatProvider provider) { return ((IConvertible)v).ToInt32 (provider); }
+ long IConvertible.ToInt64 (IFormatProvider provider) { return ((IConvertible)v).ToInt64 (provider); }
+ sbyte IConvertible.ToSByte (IFormatProvider provider) { return ((IConvertible)v).ToSByte (provider); }
+ float IConvertible.ToSingle (IFormatProvider provider) { return ((IConvertible)v).ToSingle (provider); }
+ ushort IConvertible.ToUInt16 (IFormatProvider provider) { return ((IConvertible)v).ToUInt16 (provider); }
+ uint IConvertible.ToUInt32 (IFormatProvider provider) { return ((IConvertible)v).ToUInt32 (provider); }
+ ulong IConvertible.ToUInt64 (IFormatProvider provider) { return ((IConvertible)v).ToUInt64 (provider); }
+
+ object IConvertible.ToType (Type targetType, IFormatProvider provider) {
+ return ((IConvertible)v).ToType (targetType, provider);
+ }
+
+ public static void CopyArray (IntPtr source, nfloat [] destination, int startIndex, int length)
+ {
+ if (source == IntPtr.Zero)
+ throw new ArgumentNullException ("source");
+ if (destination == null)
+ throw new ArgumentNullException ("destination");
+ if (destination.Rank != 1)
+ throw new ArgumentException ("destination", "array is multi-dimensional");
+ if (startIndex < 0)
+ throw new ArgumentException ("startIndex", "must be >= 0");
+ if (length < 0)
+ throw new ArgumentException ("length", "must be >= 0");
+ if (startIndex + length > destination.Length)
+ throw new ArgumentException ("length", "startIndex + length > destination.Length");
+
+ for (int i = 0; i < length; i++)
+ destination [i + startIndex] = (nfloat)Marshal.ReadIntPtr (source, i * nfloat.Size);
+ }
+
+ public static void CopyArray (nfloat [] source, int startIndex, IntPtr destination, int length)
+ {
+ if (source == null)
+ throw new ArgumentNullException ("source");
+ if (destination == IntPtr.Zero)
+ throw new ArgumentNullException ("destination");
+ if (source.Rank != 1)
+ throw new ArgumentException ("source", "array is multi-dimensional");
+ if (startIndex < 0)
+ throw new ArgumentException ("startIndex", "must be >= 0");
+ if (length < 0)
+ throw new ArgumentException ("length", "must be >= 0");
+ if (startIndex + length > source.Length)
+ throw new ArgumentException ("length", "startIndex + length > source.Length");
+
+ for (int i = 0; i < length; i++)
+ Marshal.WriteIntPtr (destination, i * nfloat.Size, (IntPtr)source [i + startIndex]);
+ }
+ }
+}
static void thread_end (MonoProfiler *prof, uintptr_t tid);
-static void appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result);
+static void appdomain_load (MonoProfiler *prof, MonoDomain *domain);
static void appdomain_start_unload (MonoProfiler *prof, MonoDomain *domain);
static void invalidate_each_thread (gpointer key, gpointer value, gpointer user_data);
-static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result);
+static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly);
static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly);
static void emit_type_load (gpointer key, gpointer type, gpointer user_data);
-static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result);
+static void jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo);
+
+static void jit_failed (MonoProfiler *prof, MonoMethod *method);
+
+static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo);
static void add_pending_breakpoints (MonoMethod *method, MonoJitInfo *jinfo);
mono_coop_mutex_init (&debugger_thread_exited_mutex);
mono_coop_cond_init (&debugger_thread_exited_cond);
- mono_profiler_install ((MonoProfiler*)&debugger_profiler, runtime_shutdown);
- mono_profiler_set_events ((MonoProfileFlags)(MONO_PROFILE_APPDOMAIN_EVENTS | MONO_PROFILE_THREADS | MONO_PROFILE_ASSEMBLY_EVENTS | MONO_PROFILE_JIT_COMPILATION | MONO_PROFILE_METHOD_EVENTS));
- mono_profiler_install_runtime_initialized (runtime_initialized);
- mono_profiler_install_appdomain (NULL, appdomain_load, appdomain_start_unload, appdomain_unload);
- mono_profiler_install_thread (thread_startup, thread_end);
- mono_profiler_install_assembly (NULL, assembly_load, assembly_unload, NULL);
- mono_profiler_install_jit_end (jit_end);
+ MonoProfilerHandle prof = mono_profiler_install ((MonoProfiler*)&debugger_profiler);
+ mono_profiler_set_runtime_shutdown_end_callback (prof, runtime_shutdown);
+ mono_profiler_set_runtime_initialized_callback (prof, runtime_initialized);
+ mono_profiler_set_domain_loaded_callback (prof, appdomain_load);
+ mono_profiler_set_domain_unloading_callback (prof, appdomain_start_unload);
+ mono_profiler_set_domain_unloaded_callback (prof, appdomain_unload);
+ mono_profiler_set_thread_started_callback (prof, thread_startup);
+ mono_profiler_set_thread_stopped_callback (prof, thread_end);
+ mono_profiler_set_assembly_loaded_callback (prof, assembly_load);
+ mono_profiler_set_assembly_unloading_callback (prof, assembly_unload);
+ mono_profiler_set_jit_done_callback (prof, jit_done);
+ mono_profiler_set_jit_failed_callback (prof, jit_failed);
mono_native_tls_alloc (&debugger_tls_id, NULL);
}
static void
-appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result)
+appdomain_load (MonoProfiler *prof, MonoDomain *domain)
{
mono_loader_lock ();
g_hash_table_insert (domains, domain, domain);
}
static void
-assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result)
+assembly_load (MonoProfiler *prof, MonoAssembly *assembly)
{
/* Sent later in jit_end () */
dbg_lock ();
}
static void
-jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result)
+jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
+{
+ jit_end (prof, method, jinfo);
+}
+
+static void
+jit_failed (MonoProfiler *prof, MonoMethod *method)
+{
+ jit_end (prof, method, NULL);
+}
+
+static void
+jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
{
/*
* We emit type load events when the first method of the type is JITted,
send_type_load (method->klass);
- if (!result && jinfo)
+ if (jinfo)
add_pending_breakpoints (method, jinfo);
}
#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>
}
} else {
for (opt = 0; opt < G_N_ELEMENTS (opt_sets); ++opt) {
+ /* builtin-types.cs needs OPT_INTRINS enabled */
+ if (!strcmp ("builtin-types", image->assembly_name))
+ if (!(opt_sets [opt] & MONO_OPT_INTRINS))
+ continue;
+
mini_regression_step (image, verbose, total_run, &total,
opt_sets [opt] & ~exclude,
timer, domain);
guint32 opt, action = DO_EXEC, recompilation_times = 1;
MonoGraphOptions mono_graph_options = (MonoGraphOptions)0;
int mini_verbose = 0;
- gboolean enable_profile = FALSE;
char *trace_options = NULL;
- char *profile_options = NULL;
char *aot_options = NULL;
char *forced_version = NULL;
GPtrArray *agents = NULL;
} else if (strcmp (argv [i], "--jitmap") == 0) {
mono_enable_jit_map ();
} else if (strcmp (argv [i], "--profile") == 0) {
- enable_profile = TRUE;
- profile_options = NULL;
+ mini_add_profiler_argument (NULL);
} else if (strncmp (argv [i], "--profile=", 10) == 0) {
- enable_profile = TRUE;
- profile_options = argv [i] + 10;
+ mini_add_profiler_argument (argv [i] + 10);
} else if (strncmp (argv [i], "--agent=", 8) == 0) {
if (agents == NULL)
agents = g_ptr_array_new ();
/* Set rootdir before loading config */
mono_set_rootdir ();
- if (enable_profile) {
- mini_profiler_enable_with_options (profile_options);
- }
-
mono_attach_parse_options (attach_options);
if (trace_options != NULL){
amd64_jump_reg (code, AMD64_R11);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
g_assert ((code - start) < kMaxCodeSize);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
g_assert ((code - start) < kMaxCodeSize);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE));
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops);
g_assert ((code - start) <= kMaxCodeSize);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
saved = start;
return (MonoContinuationRestore)saved;
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops);
g_assert ((code - start) < sizeof(start));
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
g_assert ((code - start) < sizeof(start));
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
start = code = mono_global_codeman_reserve (size);
mips_break (code, 0xfd);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
g_assert ((code - start) <= size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
ppc_break (code);
g_assert ((code - start) <= size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops);
g_assert ((code - start) < SZ_THROW);
mono_arch_flush_icache(start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("call_filter",
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create (corlib ? "throw_corlib_exception"
x86_ret (code);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
}
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
}
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
g_assert ((code - start) < kMaxCodeSize);
return start;
}
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
}
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
return start;
}
}
}
+ [Category ("!BITCODE")]
public static int test_1_basic_filter_catch () {
try {
MyException e = new MyException ("");
return 0;
}
+ [Category ("!BITCODE")]
public static int test_1234_complicated_filter_catch () {
string res = "init";
try {
[MethodImpl( MethodImplOptions.NoInlining )]
private static bool ExceptionFilter( byte x, FooStruct item ) => true;
+ [Category ("!BITCODE")]
public static int test_0_filter_caller_area () {
try {
throw new Exception();
return RuntimeHelpers.IsReferenceOrContainsReferences<T> ();
}
+ class IsRefClass<T> {
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public bool is_ref () {
+ return RuntimeHelpers.IsReferenceOrContainsReferences<T> ();
+ }
+ }
+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static bool is_ref_or_contains_refs_gen_ref<T> () {
return RuntimeHelpers.IsReferenceOrContainsReferences<GenStruct<T>> ();
int i;
}
+ struct AStruct3<T1, T2, T3> {
+ T1 t1;
+ T2 t2;
+ T3 t3;
+ }
+
public static int test_0_isreference_intrins () {
if (RuntimeHelpers.IsReferenceOrContainsReferences<int> ())
return 1;
if (is_ref_or_contains_refs_gen_noref<string> ())
return 10;
+ // Complex type from shared class method
+ var c1 = new IsRefClass<AStruct3<int, int, int>> ();
+ if (c1.is_ref ())
+ return 11;
+ var c2 = new IsRefClass<AStruct3<string, int, int>> ();
+ if (!c2.is_ref ())
+ return 12;
+
return 0;
}
}
gsharedvt_vphi (0);
return 0;
}
+
+ struct AStruct3<T1, T2, T3> {
+ T1 t1;
+ T2 t2;
+ T3 t3;
+ }
+
+ interface IFaceIsRef {
+ bool is_ref<T> ();
+ }
+
+ class ClassIsRef : IFaceIsRef {
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public bool is_ref<T> () {
+ return RuntimeHelpers.IsReferenceOrContainsReferences<T> ();
+ }
+ }
+
+ public static int test_0_isreference_intrins () {
+ IFaceIsRef iface = new ClassIsRef ();
+ if (iface.is_ref<AStruct3<int, int, int>> ())
+ return 1;
+ if (!iface.is_ref<AStruct3<string, int, int>> ())
+ return 2;
+ return 0;
+ }
}
// #13191
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
+ }
}
g_print ("%s)\n", args);
g_free (args);
}
- if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)
- mono_profiler_method_enter (frame->runtime_method->method);
+ if (mono_profiler_should_instrument_method (frame->runtime_method->method, TRUE))
+ MONO_PROFILER_RAISE (method_enter, (frame->runtime_method->method));
}
debug_indent_level--; \
if (tracing == 3) global_tracing = 0; \
} \
- if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE) \
- mono_profiler_method_leave (frame->runtime_method->method);
+ if (mono_profiler_should_instrument_method (frame->runtime_method->method, FALSE)) \
+ MONO_PROFILER_RAISE (method_enter, (frame->runtime_method->method));
#else
goto main_loop;
}
if (frame->ex)
- goto handle_fault;
+ goto handle_catch;
ves_abort();
MINT_IN_BREAK;
MINT_IN_CASE(MINT_LEAVE) /* Fall through */
int i;
guint32 ip_offset;
MonoExceptionClause *clause;
+ GSList *old_list = finally_ips;
MonoMethod *method = frame->runtime_method->method;
MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
clause = &rtm->clauses [i];
if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
ip = rtm->code + clause->handler_offset;
+ finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
#if DEBUG_INTERP
if (tracing)
g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
#endif
- goto main_loop;
}
}
+
+ if (old_list != finally_ips && finally_ips) {
+ ip = finally_ips->data;
+ finally_ips = g_slist_remove (finally_ips, ip);
+ sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
+ goto main_loop;
+ }
+ }
+ handle_catch:
+ {
/*
* If the handler for the exception was found in this method, we jump
* to it right away, otherwise we return and let the caller run
context->current_env = old_env;
}
- mono_profiler_method_jit (method); /* sort of... */
+ MONO_PROFILER_RAISE (jit_begin, (method));
if (mono_method_signature (method)->is_inflated)
generic_context = mono_method_get_context (method);
mono_os_mutex_lock(&calc_section);
if (runtime_method->transformed) {
mono_os_mutex_unlock(&calc_section);
- mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (jit_done, (method, runtime_method->jinfo));
return NULL;
}
runtime_method->alloca_size = runtime_method->stack_size;
runtime_method->transformed = TRUE;
mono_os_mutex_unlock(&calc_section);
- mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (jit_done, (method, NULL));
return NULL;
}
method = nm;
runtime_method->transformed = TRUE;
}
mono_os_mutex_unlock(&calc_section);
- mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (jit_done, (method, NULL));
return NULL;
} else if (!strcmp (method->name, "UnsafeStore")) {
g_error ("TODO");
if (runtime_method->transformed) {
mono_os_mutex_unlock(&calc_section);
g_free (is_bb_start);
- mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (jit_done, (method, runtime_method->jinfo));
return NULL;
}
g_free (is_bb_start);
// FIXME: Add a different callback ?
- mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (jit_done, (method, runtime_method->jinfo));
runtime_method->transformed = TRUE;
mono_os_mutex_unlock(&calc_section);
}
static void
-emit_instrumentation_call (MonoCompile *cfg, void *func)
+emit_instrumentation_call (MonoCompile *cfg, void *func, gboolean entry)
{
MonoInst *iargs [1];
if (cfg->method != cfg->current_method)
return;
- if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) {
+ if (mono_profiler_should_instrument_method (cfg->method, entry)) {
EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
mono_emit_jit_icall (cfg, func, iargs);
}
tail = FALSE;
if (tail) {
- emit_instrumentation_call (cfg, mono_profiler_method_leave);
+ emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
} else
g_assert (ctx);
g_assert (ctx->method_inst);
g_assert (ctx->method_inst->type_argc == 1);
- MonoType *t = mini_get_underlying_type (ctx->method_inst->type_argv [0]);
- MonoClass *klass = mono_class_from_mono_type (t);
+ MonoType *arg_type = ctx->method_inst->type_argv [0];
+ MonoType *t;
+ MonoClass *klass;
ins = NULL;
+ /* Resolve the argument class as possible so we can handle common cases fast */
+ t = mini_get_underlying_type (arg_type);
+ klass = mono_class_from_mono_type (t);
mono_class_init (klass);
if (MONO_TYPE_IS_REFERENCE (t))
EMIT_NEW_ICONST (cfg, ins, 1);
else {
g_assert (cfg->gshared);
- int context_used = mini_class_check_context_used (cfg, klass);
+ /* Have to use the original argument class here */
+ MonoClass *arg_class = mono_class_from_mono_type (arg_type);
+ int context_used = mini_class_check_context_used (cfg, arg_class);
/* This returns 1 or 2 */
- MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS);
+ MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, arg_class, MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS);
int dreg = alloc_ireg (cfg);
EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISUB_IMM, dreg, info->dreg, 1);
}
{
if (method->klass == mono_defaults.string_class) {
/* managed string allocation support */
- if (strcmp (method->name, "InternalAllocateStr") == 0 && !(mono_profiler_events & MONO_PROFILE_ALLOCATIONS) && !(cfg->opt & MONO_OPT_SHARED)) {
+ if (strcmp (method->name, "InternalAllocateStr") == 0 && !(cfg->opt & MONO_OPT_SHARED)) {
MonoInst *iargs [2];
MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass);
MonoMethod *managed_alloc = NULL;
cfg->dont_inline = g_list_prepend (cfg->dont_inline, method);
if (cfg->method == method) {
- if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
- cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
+ cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
/* ENTRY BLOCK */
NEW_BBLOCK (cfg, start_bblock);
CHECK_STACK_OVF (1);
n = ip [1];
CHECK_LOCAL (n);
- EMIT_NEW_LOCLOAD (cfg, ins, n);
+ if ((ip [2] == CEE_LDFLD) && ip_in_bb (cfg, cfg->cbb, ip + 2) && MONO_TYPE_ISSTRUCT (header->locals [n])) {
+ /* Avoid loading a struct just to load one of its fields */
+ EMIT_NEW_LOCLOADA (cfg, ins, n);
+ } else {
+ EMIT_NEW_LOCLOAD (cfg, ins, n);
+ }
*sp++ = ins;
ip += 2;
break;
if (cfg->gshared && mono_method_check_context_used (cmethod))
GENERIC_SHARING_FAILURE (CEE_JMP);
- emit_instrumentation_call (cfg, mono_profiler_method_leave);
+ emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
fsig = mono_method_signature (cmethod);
n = fsig->param_count + fsig->hasthis;
/* Handle tail calls similarly to normal calls */
tail_call = TRUE;
} else {
- emit_instrumentation_call (cfg, mono_profiler_method_leave);
+ emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
MONO_INST_NEW_CALL (cfg, call, OP_JMP);
call->tail_call = TRUE;
cfg->ret_var_set = TRUE;
}
} else {
- emit_instrumentation_call (cfg, mono_profiler_method_leave);
+ emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
if (cfg->lmf_var && cfg->cbb->in_count && !cfg->llvm_only)
emit_pop_lmf (cfg);
case CEE_MONO_LDPTR_CARD_TABLE:
case CEE_MONO_LDPTR_NURSERY_START:
case CEE_MONO_LDPTR_NURSERY_BITS:
- case CEE_MONO_LDPTR_INT_REQ_FLAG: {
+ case CEE_MONO_LDPTR_INT_REQ_FLAG:
+ case CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT: {
CHECK_STACK_OVF (1);
switch (ip [1]) {
case CEE_MONO_LDPTR_INT_REQ_FLAG:
ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
break;
+ case CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT:
+ ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT, NULL);
+ break;
default:
g_assert_not_reached ();
break;
CHECK_OPSIZE (4);
n = read16 (ip + 2);
CHECK_LOCAL (n);
- EMIT_NEW_LOCLOAD (cfg, ins, n);
+ if ((ip [4] == CEE_LDFLD) && ip_in_bb (cfg, cfg->cbb, ip + 4) && header->locals [n]->type == MONO_TYPE_VALUETYPE) {
+ /* Avoid loading a struct just to load one of its fields */
+ EMIT_NEW_LOCLOADA (cfg, ins, n);
+ } else {
+ EMIT_NEW_LOCLOAD (cfg, ins, n);
+ }
*sp++ = ins;
ip += 4;
break;
}
cfg->cbb = init_localsbb;
- emit_instrumentation_call (cfg, mono_profiler_method_enter);
+ emit_instrumentation_call (cfg, mono_profiler_raise_method_enter, TRUE);
if (seq_points) {
MonoBasicBlock *bb;
if (cfg->verbose_level > 2)
g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
- if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
- MonoProfileCoverageInfo *cov = cfg->coverage_info;
- g_assert (!cfg->compile_aot);
-
- cov->data [bb->dfn].cil_code = bb->cil_code;
- amd64_mov_reg_imm (code, AMD64_R11, (guint64)&cov->data [bb->dfn].count);
- /* this is not thread save, but good enough */
- amd64_inc_membase (code, AMD64_R11, 0);
- }
-
offset = code - cfg->native_code;
mono_debug_open_block (cfg, bb, offset);
MonoInst *ins;
int max_length = 0;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- max_length += 6;
/* max alignment for loops */
if ((cfg->opt & MONO_OPT_LOOP) && bb_is_loop_start (bb))
max_length += LOOP_ALIGNMENT;
} 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 */
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);
if (!has_target)
g_free (buff);
}
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
return start;
}
/* Load the vtable */
amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoObject, vtable), 8);
amd64_jump_membase (code, AMD64_RAX, offset);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
tramp_name = mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset);
*info = mono_tramp_info_create (tramp_name, start, code - start, NULL, unwind_ops);
g_assert (code - start <= size);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
g_free (name);
}
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
return start;
}
cpos = bb->max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
- //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
- //g_assert (!mono_compile_aot);
- //cpos += 6;
- //if (bb->cil_code)
- // cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
- /* this is not thread save, but good enough */
- /* fixme: howto handle overflows? */
- //x86_inc_mem (code, &cov->data [bb->dfn].count);
- }
-
if (mono_break_at_bb_method && mono_method_desc_full_match (mono_break_at_bb_method, cfg->method) && bb->block_num == mono_break_at_bb_bb_num) {
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
(gpointer)"mono_break");
MonoInst *ins = bb->code;
bb->max_offset = max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- max_offset += 6;
-
MONO_BB_FOR_EACH_INS (bb, ins)
max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
}
g_free (constant_pool_starts);
mono_arch_flush_icache ((guint8*)start, size);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
mono_stats.imt_trampolines_size += code - start;
g_assert (DISTANCE (start, code) <= size);
#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>
#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>
mono_print_thread_dump_from_ctx (ctx);
}
jit_tls->orig_ex_ctx_set = TRUE;
- mono_profiler_exception_thrown (obj);
+ MONO_PROFILER_RAISE (exception_throw, (obj));
jit_tls->orig_ex_ctx_set = FALSE;
res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
- mono_profiler_exception_clause_handler (method, ei->flags, i, ex_obj);
+ MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
mini_set_abort_threshold (ctx);
if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
- mono_profiler_exception_clause_handler (method, ei->flags, i, ex_obj);
+ MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
mini_set_abort_threshold (ctx);
call_filter (ctx, ei->handler_start);
if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
- mono_profiler_exception_clause_handler (method, ei->flags, i, ex_obj);
+ MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->exceptions_finallys++;
}
jit_tls->orig_ex_ctx_set = TRUE;
- mono_profiler_exception_method_leave (method);
+ MONO_PROFILER_RAISE (method_exception_leave, (method, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
*ctx = new_ctx;
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);
}
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
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
* 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);
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++;
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);
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);
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;
}
}
}
}
- /*
- * The INDIRECT flag added by OP_LDADDR inhibits optimizations, even if the LDADDR
- * was later optimized away, so clear these flags, and add them back for the still
- * present OP_LDADDR instructions.
- */
- for (i = 0; i < cfg->next_vreg; ++i) {
- MonoInst *ins;
-
- ins = get_vreg_to_inst (cfg, i);
- if (ins && ins != cfg->rgctx_var)
- ins->flags &= ~MONO_INST_INDIRECT;
- }
-
/*
* Make a first pass over the code to precreate PHI nodes/set INDIRECT flags.
*/
}
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;
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)
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;
cpos = bb->max_offset;
-#if 0
- if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
- MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
- g_assert (!mono_compile_aot);
- cpos += 20;
- if (bb->cil_code)
- cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
- /* this is not thread save, but good enough */
- /* fixme: howto handle overflows? */
- mips_load_const (code, mips_at, &cov->data [bb->dfn].count);
- mips_lw (code, mips_temp, mips_at, 0);
- mips_addiu (code, mips_temp, mips_temp, 1);
- mips_sw (code, mips_temp, mips_at, 0);
- }
-#endif
MONO_BB_FOR_EACH_INS (bb, ins) {
offset = code - cfg->native_code;
MonoInst *ins = bb->code;
bb->max_offset = max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- max_offset += 6;
-
MONO_BB_FOR_EACH_INS (bb, ins)
max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
}
return TRUE;
if (!strcmp ("Xamarin.WatchOS", klass->image->assembly_name))
return TRUE;
+ /* regression test suite */
+ if (!strcmp ("builtin-types", klass->image->assembly_name))
+ return TRUE;
return FALSE;
}
#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>
}
}
-#if defined(__i386__) || defined(__x86_64__)
-#define FULL_STAT_PROFILER_BACKTRACE 1
-#define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
-#define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
-#if MONO_ARCH_STACK_GROWS_UP
-#define IS_BEFORE_ON_STACK <
-#define IS_AFTER_ON_STACK >
-#else
-#define IS_BEFORE_ON_STACK >
-#define IS_AFTER_ON_STACK <
-#endif
-#else
-#define FULL_STAT_PROFILER_BACKTRACE 0
-#endif
-
#if (defined (USE_POSIX_BACKEND) && defined (SIGRTMIN)) || defined (SIGPROF)
#define HAVE_PROFILER_SIGNAL
#endif
#ifdef HAVE_PROFILER_SIGNAL
-static void
-per_thread_profiler_hit (void *ctx)
-{
- int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
- MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
-
- if (call_chain_depth == 0) {
- mono_profiler_stat_hit ((guchar *)mono_arch_ip_from_context (ctx), ctx);
- } else {
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
- int current_frame_index = 1;
- MonoContext mono_context;
- guchar *ips [call_chain_depth + 1];
-
- mono_sigctx_to_monoctx (ctx, &mono_context);
- ips [0] = (guchar *)MONO_CONTEXT_GET_IP (&mono_context);
-
- if (jit_tls != NULL) {
- if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
-#if FULL_STAT_PROFILER_BACKTRACE
- guchar *current_frame;
- guchar *stack_bottom;
- guchar *stack_top;
-
- stack_bottom = (guchar *)jit_tls->end_of_stack;
- stack_top = (guchar *)MONO_CONTEXT_GET_SP (&mono_context);
- current_frame = (guchar *)MONO_CONTEXT_GET_BP (&mono_context);
-
- while ((current_frame_index <= call_chain_depth) &&
- (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
- ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
- ips [current_frame_index] = (guchar *)CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
- current_frame_index ++;
- stack_top = current_frame;
- current_frame = (guchar *)CURRENT_FRAME_GET_BASE_POINTER (current_frame);
- }
-#else
- call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
-#endif
- }
-
- if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
-#if GLIBC_PROFILER_BACKTRACE
- current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
-#else
- call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
-#endif
- }
-
- if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
- MonoDomain *domain = mono_domain_get ();
- if (domain != NULL) {
- MonoLMF *lmf = NULL;
- MonoJitInfo *ji;
- MonoJitInfo res;
- MonoContext new_mono_context;
- int native_offset;
- ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
- &new_mono_context, NULL, &lmf, &native_offset, NULL);
- while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
- ips [current_frame_index] = (guchar *)MONO_CONTEXT_GET_IP (&new_mono_context);
- current_frame_index ++;
- mono_context = new_mono_context;
- ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
- &new_mono_context, NULL, &lmf, &native_offset, NULL);
- }
- }
- }
- }
-
- mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
- }
-}
-
static MonoNativeThreadId sampling_thread;
static gint32 profiler_signals_sent;
int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
mono_thread_info_set_is_async_context (TRUE);
- per_thread_profiler_hit (ctx);
+
+ MONO_PROFILER_RAISE (sample_hit, (mono_arch_ip_from_context (ctx), ctx));
+
mono_thread_info_set_is_async_context (FALSE);
mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
static clock_serv_t sampling_clock_service;
static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
{
kern_return_t ret;
clockid_t sampling_posix_clock;
static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
{
- switch (mono_profiler_get_sampling_mode ()) {
- case MONO_PROFILER_STAT_MODE_PROCESS: {
+ switch (mode) {
+ case MONO_PROFILER_SAMPLE_MODE_PROCESS: {
/*
* If we don't have clock_nanosleep (), measuring the process time
* makes very little sense as we can only use nanosleep () to sleep on
// fallthrough
}
- case MONO_PROFILER_STAT_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
+ case MONO_PROFILER_SAMPLE_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
default: g_assert_not_reached (); break;
}
}
mono_threads_attach_tools_thread ();
mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler sampler");
- gint64 rate = 1000000000 / mono_profiler_get_sampling_rate ();
-
int old_policy;
struct sched_param old_sched;
pthread_getschedparam (pthread_self (), &old_policy, &old_sched);
struct sched_param sched = { .sched_priority = sched_get_priority_max (SCHED_FIFO) };
pthread_setschedparam (pthread_self (), SCHED_FIFO, &sched);
- clock_init ();
+ MonoProfilerSampleMode mode;
+
+init:
+ mono_profiler_get_sample_mode (NULL, &mode, NULL);
- guint64 sleep = clock_get_time_ns ();
+ if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) {
+ mono_profiler_sampling_thread_wait ();
- while (InterlockedRead (&sampling_thread_running)) {
- sleep += rate;
+ 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)) {
+ uint32_t freq;
+ MonoProfilerSampleMode new_mode;
+
+ mono_profiler_get_sample_mode (NULL, &new_mode, &freq);
+
+ if (new_mode != mode) {
+ clock_cleanup ();
+ goto init;
+ }
+
+ sleep += 1000000000 / freq;
FOREACH_THREAD_SAFE (info) {
/* info should never be this thread as we're a tools thread. */
mono_threads_pthread_kill (info, profiler_signal);
InterlockedIncrement (&profiler_signals_sent);
} FOREACH_THREAD_SAFE_END
-
- clock_sleep_ns_abs (sleep);
}
- 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 ();
{
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
cpos = bb->max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
- //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
- //g_assert (!mono_compile_aot);
- //cpos += 6;
- //if (bb->cil_code)
- // cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
- /* this is not thread save, but good enough */
- /* fixme: howto handle overflows? */
- //x86_inc_mem (code, &cov->data [bb->dfn].count);
- }
-
MONO_BB_FOR_EACH_INS (bb, ins) {
offset = code - cfg->native_code;
MonoInst *ins;
bb->max_offset = max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- max_offset += 6;
-
MONO_BB_FOR_EACH_INS (bb, ins)
max_offset += ins_native_length (cfg, ins);
}
#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>
#endif
GList* mono_aot_paths;
-static gboolean mini_enable_profiler = FALSE;
-static char* mini_profiler_options = NULL;
+static GPtrArray *profile_options;
static GSList *tramp_infos;
static void register_icalls (void);
-static gboolean mini_profiler_enabled (void) { return mini_enable_profiler; }
-static const char* mini_profiler_get_options (void) { return mini_profiler_options; }
-
gboolean
mono_running_on_valgrind (void)
{
mono_debug_count (void)
{
static int count = 0, int_val = 0;
- static gboolean inited;
+ static gboolean inited, has_value = FALSE;
count ++;
if (value) {
int_val = atoi (value);
g_free (value);
+ has_value = TRUE;
}
inited = TRUE;
}
- if (!int_val)
+ if (!has_value)
return TRUE;
if (count == int_val)
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
case MONO_PATCH_INFO_AOT_MODULE:
case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
+ case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
return (ji->type << 8);
case MONO_PATCH_INFO_CASTCLASS_CACHE:
return (ji->type << 8) | (ji->data.index);
target = mi->func;
break;
}
+ case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT: {
+ target = (gpointer) &mono_profiler_state.gc_allocation_count;
+ break;
+ }
default:
g_assert_not_reached ();
}
}
void
-mini_profiler_enable_with_options (const char* profile_options)
+mini_add_profiler_argument (const char *desc)
{
- mini_enable_profiler = TRUE;
- mini_profiler_options = g_strdup (profile_options);
+ if (!profile_options)
+ profile_options = g_ptr_array_new ();
+
+ g_ptr_array_add (profile_options, (gpointer) desc);
}
MonoDomain *
mono_install_get_class_from_name (mono_aot_get_class_from_name);
mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
- if (mini_profiler_enabled ()) {
- mono_profiler_load (mini_profiler_get_options ());
- mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main");
- }
+ if (profile_options)
+ for (guint i = 0; i < profile_options->len; i++)
+ mono_profiler_load ((const char *) g_ptr_array_index (profile_options, i));
+
+ mono_profiler_started ();
if (debug_options.collect_pagefault_stats)
mono_aot_set_make_unreadable (TRUE);
mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
mono_error_assert_ok (&error);
mono_thread_attach (domain);
+ MONO_PROFILER_RAISE (thread_name, (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main"));
#endif
- if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
+ if (mono_profiler_sampling_enabled ())
mono_runtime_setup_stat_profiler ();
- mono_profiler_runtime_initialized ();
+ MONO_PROFILER_RAISE (runtime_initialized, ());
MONO_VES_INIT_END ();
* the wrapper would call the icall which would call the wrapper and
* so on.
*/
- register_icall (mono_profiler_method_enter, "mono_profiler_method_enter", "void ptr", TRUE);
- register_icall (mono_profiler_method_leave, "mono_profiler_method_leave", "void ptr", TRUE);
+ register_icall (mono_profiler_raise_method_enter, "mono_profiler_raise_method_enter", "void ptr", TRUE);
+ register_icall (mono_profiler_raise_method_leave, "mono_profiler_raise_method_leave", "void ptr", TRUE);
register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
void
mini_cleanup (MonoDomain *domain)
{
- if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
+ if (mono_profiler_sampling_enabled ())
mono_runtime_shutdown_stat_profiler ();
+ MONO_PROFILER_RAISE (runtime_shutdown_begin, ());
+
#ifndef DISABLE_COM
cominterop_release_all_rcws ();
#endif
mono_threadpool_cleanup ();
- mono_profiler_shutdown ();
+ MONO_PROFILER_RAISE (runtime_shutdown_end, ());
+
+ mono_profiler_cleanup ();
+
+ if (profile_options)
+ g_ptr_array_free (profile_options, TRUE);
free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
if (cfg->verbose_level > 2)
g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
- if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
- MonoProfileCoverageInfo *cov = cfg->coverage_info;
- g_assert (!mono_compile_aot);
- cov->data [bb->dfn].cil_code = bb->cil_code;
- /* This is not thread save, but good enough */
- S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
- s390_alsi (code, 0, s390_r1, 1);
- }
-
MONO_BB_FOR_EACH_INS (bb, ins) {
offset = code - cfg->native_code;
MonoInst *ins;
bb->max_offset = max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- max_offset += 6;
-
MONO_BB_FOR_EACH_INS (bb, ins)
max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
}
mono_arch_flush_icache (start, size);
}
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
if (has_target) {
*info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
}
mono_arch_flush_icache ((guint8*)start, (code - start));
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
if (!fail_tramp)
mono_stats.imt_trampolines_size += (code - start);
cpos = bb->max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
- NOT_IMPLEMENTED;
- }
-
MONO_BB_FOR_EACH_INS (bb, ins) {
guint8* code_start;
#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>
context.ContextFlags = CONTEXT_CONTROL;
if (GetThreadContext (thread, &context)) {
+ guchar *ip;
+
#ifdef _WIN64
- mono_profiler_stat_hit ((guchar *) context.Rip, &context);
+ ip = (guchar *) context.Rip;
#else
- mono_profiler_stat_hit ((guchar *) context.Eip, &context);
+ ip = (guchar *) context.Eip;
#endif
+
+ MONO_PROFILER_RAISE (sample_hit, (ip, &context));
}
}
cpos = bb->max_offset;
- if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
- MonoProfileCoverageInfo *cov = cfg->coverage_info;
- g_assert (!cfg->compile_aot);
- cpos += 6;
-
- cov->data [bb->dfn].cil_code = bb->cil_code;
- /* this is not thread save, but good enough */
- x86_inc_mem (code, &cov->data [bb->dfn].count);
- }
-
offset = code - cfg->native_code;
mono_debug_open_block (cfg, bb, offset);
MonoInst *ins;
bb->max_offset = max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- max_offset += 6;
/* max alignment for loops */
if ((cfg->opt & MONO_OPT_LOOP) && bb_is_loop_start (bb))
max_offset += LOOP_ALIGNMENT;
g_free (buff);
}
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
if (!has_target)
g_free (buff);
}
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
return start;
}
/* Load the vtable */
x86_mov_reg_membase (code, X86_EAX, X86_ECX, MONO_STRUCT_OFFSET (MonoObject, vtable), 4);
x86_jump_membase (code, X86_EAX, offset);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
tramp_name = mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset);
*info = mono_tramp_info_create (tramp_name, start, code - start, NULL, unwind_ops);
#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>
if (cfg->verbose_level > 2)
g_print ("creating locals\n");
- for (i = 0; i < header->num_locals; ++i)
+ for (i = 0; i < header->num_locals; ++i) {
+ if (cfg->verbose_level > 2)
+ g_print ("\tlocal [%d]: ", i);
cfg->locals [i] = mono_compile_create_var (cfg, header->locals [i], OP_LOCAL);
+ }
if (cfg->verbose_level > 2)
g_print ("locals done\n");
mono_bb_deduplicate_op_il_seq_points (cfg, bb);
}
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, cfg->num_bblocks);
-
code = mono_arch_emit_prolog (cfg);
cfg->code_len = code - cfg->native_code;
} else {
mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
}
- mono_profiler_code_buffer_new (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method);
+ MONO_PROFILER_RAISE (jit_code_buffer, (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method));
mono_arch_flush_icache (cfg->native_code, cfg->code_len);
static char *verbose_method_name;
InterlockedIncrement (&mono_jit_stats.methods_compiled);
- if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
- mono_profiler_method_jit (method);
+ MONO_PROFILER_RAISE (jit_begin, (method));
if (MONO_METHOD_COMPILE_BEGIN_ENABLED ())
MONO_PROBE_METHOD_COMPILE_BEGIN (method);
cfg->method = method_to_compile;
cfg->mempool = mono_mempool_new ();
cfg->opt = opts;
- cfg->prof_options = mono_profiler_get_events ();
cfg->run_cctors = run_cctors;
cfg->domain = domain;
cfg->verbose_level = mini_verbose;
MonoJitInfo *jinfo, *info;
MonoVTable *vtable;
MonoException *ex = NULL;
- guint32 prof_options;
GTimer *jit_timer;
MonoMethod *prof_method, *shared;
if (!jinfo)
jinfo = mono_jit_info_table_find (mono_domain_get (), (char *)code);
if (jinfo)
- mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
+ MONO_PROFILER_RAISE (jit_done, (method, jinfo));
return code;
} else if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
const char *name = method->name;
}
if (ex) {
- if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
- mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
+ MONO_PROFILER_RAISE (jit_failed, (method));
mono_destroy_compile (cfg);
mono_error_set_exception_instance (error, ex);
jinfo = cfg->jit_info;
- prof_options = cfg->prof_options;
-
/*
* Update global stats while holding a lock, instead of doing many
* InterlockedIncrement operations during JITting.
return NULL;
}
- if (prof_options & MONO_PROFILE_JIT_COMPILATION) {
- if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
- if (mono_marshal_method_from_wrapper (method)) {
- /* Native func wrappers have no method */
- /* The profiler doesn't know about wrappers, so pass the original icall method */
- mono_profiler_method_end_jit (mono_marshal_method_from_wrapper (method), jinfo, MONO_PROFILE_OK);
- }
- }
- mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
- if (prof_method != method) {
- mono_profiler_method_end_jit (prof_method, jinfo, MONO_PROFILE_OK);
+ if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+ if (mono_marshal_method_from_wrapper (method)) {
+ /* Native func wrappers have no method */
+ /* The profiler doesn't know about wrappers, so pass the original icall method */
+ MONO_PROFILER_RAISE (jit_done, (mono_marshal_method_from_wrapper (method), jinfo));
}
}
+ MONO_PROFILER_RAISE (jit_done, (method, jinfo));
+ if (prof_method != method)
+ MONO_PROFILER_RAISE (jit_done, (prof_method, jinfo));
if (!(method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE ||
method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
guint epilog_end;
regmask_t used_int_regs;
guint32 opt;
- guint32 prof_options;
guint32 flags;
guint32 comp_done;
guint32 verbose_level;
gpointer debug_info;
guint32 lmf_offset;
guint16 *intvars;
- MonoProfileCoverageInfo *coverage_info;
+ MonoProfilerCoverageInfo *coverage_info;
GHashTable *token_info_hash;
MonoCompileArch arch;
guint32 inline_depth;
void mini_cleanup (MonoDomain *domain);
MONO_API MonoDebugOptions *mini_get_debug_options (void);
MONO_API gboolean mini_parse_debug_option (const char *option);
-void mini_profiler_enable_with_options (const char *profile_options);
+void mini_add_profiler_argument (const char *desc);
/* graph dumping */
void mono_cfg_dump_create_context (MonoCompile *cfg);
* Same as JIT_ICALL_ADDR, but not treated as a call.
*/
PATCH_INFO(JIT_ICALL_ADDR_NOCALL, "jit_icall_addr_nocall")
+PATCH_INFO(PROFILER_ALLOCATION_COUNT, "profiler_allocation_count")
g_assert ((code - start) < buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
addr = thunk_start;
g_assert ((((guint64)(addr)) >> 32) == 0);
mono_arch_flush_icache (thunk_start, thunk_code - thunk_start);
- mono_profiler_code_buffer_new (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
}
if (can_write) {
InterlockedExchange ((gint32*)(orig_code - 4), ((gint64)addr - (gint64)orig_code));
*(guint64*)thunk_code = (guint64)addr;
addr = thunk_start;
mono_arch_flush_icache (thunk_start, thunk_code - thunk_start);
- mono_profiler_code_buffer_new (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
return addr;
}
#endif /* !DISABLE_JIT */
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE));
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
tramp_name = mono_get_generic_trampoline_name (tramp_type);
*info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
*code_len = size;
mono_arch_flush_icache (buf, size);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type));
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
return buf;
}
}
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
amd64_jump_reg (code, AMD64_R11);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
amd64_jump_reg (code, AMD64_RAX);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
g_assert (code - buf <= tramp_size);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
amd64_ret (code);
mono_arch_flush_icache (code, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
g_assert (code - buf <= tramp_size);
g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE));
g_assert (code - start < buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("enter_icall_trampoline", start, code - start, ji, unwind_ops);
/* Flush instruction cache, since we've generated code */
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
/* Sanity check */
g_assert ((code - buf) <= buf_len);
/* Flush instruction cache, since we've generated code */
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type));
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
g_assert ((code - buf) <= size);
*(guint32*)code = (guint32)addr;
code += 4;
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
g_assert ((code - start) <= size);
/*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
g_print ("unbox code is at %p for method at %p\n", start, addr);*/
g_assert ((code - start) <= buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
}
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
code = emit_bx (code, ARMREG_R1);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
/* Obtain jit_tls->handler_block_return_address */
if (aot) {
code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_R0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_arm_handler_block_trampoline_helper");
- ARM_B (code, 0);
} else {
ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
ARM_B (code, 0);
*(gpointer*)code = mono_arm_handler_block_trampoline_helper;
code += 4;
}
-
+ ARM_BLX_REG (code, ARMREG_R0);
/* Set it as the return address so the trampoline will return to it */
ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_R0);
}
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
g_assert (code - buf <= tramp_size);
*info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
ARM_LDM (code, ARMREG_IP, 0xffff);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
const char *tramp_name = single_step ? "sdb_single_step_trampoline" : "sdb_breakpoint_trampoline";
*info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
g_assert (code - start < buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("enter_icall_trampoline", start, code - start, ji, unwind_ops);
g_assert ((code - buf) <= buf_len);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, buf, code - buf, NULL, NULL), domain);
/*
* We are in a method frame after the call emitted by OP_CALL_HANDLER.
*/
+ /* Call a helper to obtain jit_tls->handler_block_return_address */
if (aot)
code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_arm_handler_block_trampoline_helper");
else
code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_arm_handler_block_trampoline_helper);
+ arm_blrx (code, ARMREG_IP0);
/* Set it as the return address so the trampoline will return to it */
- arm_movx (code, ARMREG_LR, ARMREG_IP0);
+ arm_movx (code, ARMREG_LR, ARMREG_R0);
- /* Call the trampoline */
+ /* Call the C trampoline function */
if (aot) {
char *name = g_strdup_printf ("trampoline_func_%d", MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD);
code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, name);
arm_brx (code, ARMREG_IP0);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
g_assert (code - buf <= tramp_size);
*info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
g_assert (code - start < buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
*info = mono_tramp_info_create ("enter_icall_trampoline", start, code - start, ji, unwind_ops);
g_assert ((code - start) <= 28);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, method);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, method));
snprintf(trampName, sizeof(trampName), "%s_unbox_trampoline", method->name);
/* Flush instruction cache, since we've generated code */
mono_arch_flush_icache (code, buf - code);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (info);
tramp_name = mono_get_generic_trampoline_name (tramp_type);
/* Flush instruction cache, since we've generated code */
mono_arch_flush_icache (code, buf - code);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE,
- (void *) mono_get_generic_trampoline_simple_name (tramp_type));
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf,
+ MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE,
+ (void *) mono_get_generic_trampoline_simple_name (tramp_type)));
/* Sanity check */
g_assert ((buf - code) <= SPECIFIC_TRAMPOLINE_SIZE);
s390_jg (code, displace);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
g_assert ((code - start) < buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
s390_br (code, s390_r1);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
g_assert (code - buf <= tramp_size);
*info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
x86_jump_code (code, addr);
g_assert ((code - start) < size);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
g_assert ((code - start) <= buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
}
g_assert ((code - buf) <= 256);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
tramp_name = mono_get_generic_trampoline_name (tramp_type);
*info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
g_assert ((buf - code) <= TRAMPOLINE_SIZE);
mono_arch_flush_icache (code, buf - code);
- mono_profiler_code_buffer_new (code, buf - code, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type));
+ MONO_PROFILER_RAISE (jit_code_buffer, (code, buf - code, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
if (code_len)
*code_len = buf - code;
}
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
x86_jump_reg (code, X86_EAX);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
x86_jump_code (code, tramp);
mono_arch_flush_icache (buf, code - buf);
- mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
g_assert (code - buf <= tramp_size);
*info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
g_assert ((code - start) <= buf_len);
mono_arch_flush_icache (start, code - start);
- mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
/*
- * 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)
static gboolean verbose;
static void
-prof_jit_enter (MonoProfiler *prof, MonoMethod *method)
-{
-}
-
-static void
-prof_jit_leave (MonoProfiler *prof, MonoMethod *method, int result)
+prof_jit_leave (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
{
MonoImage *image = mono_class_get_image (mono_method_get_class (method));
}
void
-mono_profiler_startup (const char *desc);
+mono_profiler_init_aot (const char *desc);
/**
- * mono_profiler_startup:
+ * mono_profiler_init_aot:
* the entry point
*/
void
-mono_profiler_startup (const char *desc)
+mono_profiler_init_aot (const char *desc)
{
MonoProfiler *prof;
const char *p;
const char *opt;
- char *outfile_name;
+ char *outfile_name = NULL;
p = desc;
if (strncmp (p, "aot", 3))
mono_os_mutex_init (&mutex);
- mono_profiler_install (prof, prof_shutdown);
-
- mono_profiler_install_jit_compile (prof_jit_enter, prof_jit_leave);
-
- mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+ MonoProfilerHandle handle = mono_profiler_install (prof);
+ mono_profiler_set_runtime_shutdown_end_callback (handle, prof_shutdown);
+ mono_profiler_set_jit_done_callback (handle, prof_jit_leave);
}
static void
/*
- * mono-profiler-iomap.c: IOMAP string profiler for Mono.
+ * iomap.c: IOMAP string profiler for Mono.
*
* Authors:
* Marek Habersack <mhabersack@novell.com>
static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries);
static inline void store_string_location (MonoProfiler *prof, const gchar *string, guint32 hash, size_t len);
static void mono_portability_remember_string (MonoProfiler *prof, MonoDomain *domain, MonoString *str);
-void mono_profiler_startup (const char *desc);
+void mono_profiler_init_iomap (const char *desc);
static void mismatched_stats_foreach_func (gpointer key, gpointer value, gpointer user_data)
{
static MonoClass *string_class = NULL;
-static void mono_portability_remember_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
+static void mono_portability_remember_alloc (MonoProfiler *prof, MonoObject *obj)
{
- if (klass != string_class)
+ if (mono_object_get_class (obj) != string_class)
return;
mono_portability_remember_string (prof, mono_object_get_domain (obj), (MonoString*)obj);
}
mono_os_mutex_destroy (&mismatched_files_section);
}
-void mono_profiler_startup (const char *desc)
+void mono_profiler_init_iomap (const char *desc)
{
MonoProfiler *prof = g_new0 (MonoProfiler, 1);
prof->saved_strings_hash = g_hash_table_new (NULL, NULL);
prof->string_locations_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);
- mono_profiler_install (prof, profiler_shutdown);
- mono_profiler_install_runtime_initialized (runtime_initialized_cb);
- mono_profiler_install_iomap (mono_portability_iomap_event);
- mono_profiler_install_allocation (mono_portability_remember_alloc);
-
- mono_profiler_set_events ((MonoProfileFlags)(MONO_PROFILE_ALLOCATIONS | MONO_PROFILE_IOMAP_EVENTS));
+ MonoProfilerHandle handle = mono_profiler_install (prof);
+ mono_profiler_set_runtime_shutdown_end_callback (handle, profiler_shutdown);
+ mono_profiler_set_runtime_initialized_callback (handle, runtime_initialized_cb);
+ mono_profiler_set_iomap_report_callback (handle, mono_portability_iomap_event);
+ mono_profiler_enable_allocations ();
+ mono_profiler_set_gc_allocation_callback (handle, mono_portability_remember_alloc);
}
#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)
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_STAT_MODE_REAL;
- } else if (match_option (arg, "sampling-process", NULL)) {
- config->sampling_mode = MONO_PROFILER_STAT_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)) {
- config->enable_mask |= PROFLOG_PERF_SAMPLING_ALIAS;
set_sample_freq (config, val);
+ 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)) {
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;
if (config->cov_filter_files == NULL)
config->cov_filter_files = g_ptr_array_new ();
g_ptr_array_add (config->cov_filter_files, g_strdup (val));
- } else if (match_option (arg, "onlycoverage", NULL)) {
- config->only_coverage = TRUE;
} else {
int i;
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);
}
}
//XXX change this to header constants
config->max_allocated_sample_hits = mono_cpu_count () * 1000;
+ config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_NONE;
config->sample_freq = 100;
config->max_call_depth = 100;
config->num_frames = MAX_FRAMES;
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");
}
/*
- * 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 only_coverage = 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;
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] GC handle type (System.Runtime.InteropServices.GCHandleType)
- * 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] GC handle type (System.Runtime.InteropServices.GCHandleType)
- * 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] MONO_PROFILER_MONITOR_{CONTENTION,FAIL,DONE}
- * [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;
typedef struct {
MonoLinkedListSetNode node;
- // Convenience pointer to the profiler structure.
- MonoProfiler *profiler;
-
// Was this thread added to the LLS?
gboolean attached;
#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
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;
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)
{
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)
{
}
static MonoProfilerThread *
-init_thread (MonoProfiler *prof, gboolean add_to_lls)
+init_thread (gboolean add_to_lls)
{
MonoProfilerThread *thread = PROF_TLS_GET ();
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;
*/
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);
}
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.
*
* The lock does not support recursion.
*/
-static volatile gint32 buffer_lock_state;
-static volatile gint32 buffer_lock_exclusive_intent;
static void
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_;
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) {
}
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;
}
{
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)
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
{
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;
{
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
}
static void
-emit_ptr (LogBuffer *logbuffer, void *ptr)
+emit_ptr (LogBuffer *logbuffer, const void *ptr)
{
if (!logbuffer->ptr_base)
logbuffer->ptr_base = (uintptr_t) ptr;
{
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;
}
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 ();
*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);
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
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);
{
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);
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);
}
}
}
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.
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);
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 */ +
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, int num, void **objects, int *root_types, uintptr_t *extra_info)
+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 */ +
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, MonoGCEvent ev, int 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;
- }
- }
-
-
+gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
+{
if (ENABLED (PROFLOG_GC_EVENTS)) {
ENTER_LOG (&gc_events_ctr, logbuffer,
EVENT_SIZE /* event */ +
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:
/*
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;
+
+ log_profiler.do_heap_walk = FALSE;
+ log_profiler.last_hs_time = current_time ();
- if (do_heap_shot && do_heap_walk) {
- do_heap_walk = FALSE;
- heapshot_requested = 0;
- last_hs_time = current_time ();
+ InterlockedWrite (&log_profiler.heapshot_requested, 0);
}
/*
*/
if (ENABLED (ALL_GC_EVENTS_MASK))
sync_point_mark (SYNC_POINT_WORLD_START);
+
break;
case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED:
/*
* their buffers again.
*/
buffer_unlock_excl ();
+
break;
default:
break;
}
static void
-gc_resize (MonoProfiler *profiler, int64_t new_size)
+gc_resize (MonoProfiler *profiler, uintptr_t new_size)
{
ENTER_LOG (&gc_resizes_ctr, logbuffer,
EVENT_SIZE /* event */ +
emit_event (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
emit_value (logbuffer, new_size);
- EXIT_LOG_EXPLICIT (DO_SEND);
+ EXIT_LOG;
}
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;
}
/*
}
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)
}
static void
-gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
+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 */
);
emit_event (logbuffer, do_bt | TYPE_ALLOC);
- emit_ptr (logbuffer, klass);
+ emit_ptr (logbuffer, mono_object_get_class (obj));
emit_obj (logbuffer, obj);
emit_value (logbuffer, len);
if (do_bt)
- emit_bt (prof, logbuffer, &data);
+ emit_bt (logbuffer, &data);
EXIT_LOG;
}
static void
-gc_moves (MonoProfiler *prof, void **objects, int num)
+gc_moves (MonoProfiler *prof, MonoObject *const *objects, uint64_t num)
{
ENTER_LOG (&gc_moves_ctr, logbuffer,
EVENT_SIZE /* event */ +
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, int type, uintptr_t handle, MonoObject *obj)
+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)
emit_obj (logbuffer, obj);
if (do_bt)
- emit_bt (prof, logbuffer, &data);
+ emit_bt (logbuffer, &data);
EXIT_LOG;
}
+static void
+gc_handle_created (MonoProfiler *prof, uint32_t handle, MonoGCHandleType type, MonoObject *obj)
+{
+ gc_handle (prof, MONO_PROFILER_GC_HANDLE_CREATED, type, handle, obj);
+}
+
+static void
+gc_handle_deleted (MonoProfiler *prof, uint32_t handle, MonoGCHandleType type)
+{
+ gc_handle (prof, MONO_PROFILER_GC_HANDLE_DESTROYED, type, handle, NULL);
+}
+
static void
finalize_begin (MonoProfiler *prof)
{
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 */
);
}
static void
-image_loaded (MonoProfiler *prof, MonoImage *image, int result)
+image_loaded (MonoProfiler *prof, MonoImage *image)
{
- if (result != MONO_PROFILE_OK)
- return;
-
const char *name = mono_image_get_filename (image);
int nlen = strlen (name) + 1;
}
static void
-assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly, int result)
+assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly)
{
- if (result != MONO_PROFILE_OK)
- return;
-
char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
int nlen = strlen (name) + 1;
MonoImage *image = mono_assembly_get_image (assembly);
}
static void
-class_loaded (MonoProfiler *prof, MonoClass *klass, int result)
+class_loaded (MonoProfiler *prof, MonoClass *klass)
{
- if (result != MONO_PROFILE_OK)
- return;
-
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);
EXIT_LOG;
- if (runtime_inited)
+ if (InterlockedRead (&log_profiler.runtime_inited))
mono_free (name);
else
g_free (name);
}
-static void process_method_enter_coverage (MonoProfiler *prof, MonoMethod *method);
-
static void
method_enter (MonoProfiler *prof, MonoMethod *method)
{
- process_method_enter_coverage (prof, method);
-
- if (!only_coverage && 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 */
static void
method_leave (MonoProfiler *prof, MonoMethod *method)
{
- if (!only_coverage && --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 */
}
static void
-method_exc_leave (MonoProfiler *prof, MonoMethod *method)
+method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
{
- if (!only_coverage && !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 */
}
}
-static void
-method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji, int result)
+static MonoProfilerCallInstrumentationFlags
+method_filter (MonoProfiler *prof, MonoMethod *method)
{
- if (result != MONO_PROFILE_OK)
- return;
+ return MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+}
+static void
+method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji)
+{
buffer_lock ();
register_method_local (method, ji);
}
static void
-code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
+code_buffer_new (MonoProfiler *prof, const mono_byte *buffer, uint64_t size, MonoProfilerCodeBufferType type, const void *data)
{
- char *name;
+ const char *name;
int nlen;
if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
- name = (char *) data;
+ name = (const char *) data;
nlen = strlen (name) + 1;
} else {
name = NULL;
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)
emit_obj (logbuffer, object);
if (do_bt)
- emit_bt (prof, logbuffer, &data);
+ emit_bt (logbuffer, &data);
EXIT_LOG;
}
static void
-clause_exc (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num, MonoObject *exc)
+clause_exc (MonoProfiler *prof, MonoMethod *method, uint32_t clause_num, MonoExceptionEnum clause_type, MonoObject *exc)
{
ENTER_LOG (&exception_clauses_ctr, logbuffer,
EVENT_SIZE /* event */ +
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)
emit_obj (logbuffer, object);
if (do_bt)
- emit_bt (profiler, logbuffer, &data);
+ emit_bt (logbuffer, &data);
EXIT_LOG;
}
+static void
+monitor_contention (MonoProfiler *prof, MonoObject *object)
+{
+ monitor_event (prof, object, MONO_PROFILER_MONITOR_CONTENTION);
+}
+
+static void
+monitor_acquired (MonoProfiler *prof, MonoObject *object)
+{
+ monitor_event (prof, object, MONO_PROFILER_MONITOR_DONE);
+}
+
+static void
+monitor_failed (MonoProfiler *prof, MonoObject *object)
+{
+ monitor_event (prof, object, MONO_PROFILER_MONITOR_FAIL);
+}
+
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 ();
{
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
-domain_loaded (MonoProfiler *prof, MonoDomain *domain, int result)
+domain_loaded (MonoProfiler *prof, MonoDomain *domain)
{
- if (result != MONO_PROFILE_OK)
- return;
-
ENTER_LOG (&domain_loads_ctr, logbuffer,
EVENT_SIZE /* event */ +
BYTE_SIZE /* type */ +
typedef struct {
MonoLockFreeQueueNode node;
- MonoProfiler *prof;
uint64_t time;
uintptr_t tid;
- void *ip;
+ const void *ip;
int count;
AsyncFrameInfo frames [MONO_ZERO_LEN_ARRAY];
} SampleHit;
{
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;
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))
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
-mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context)
+mono_sample_hit (MonoProfiler *profiler, const mono_byte *ip, const void *context)
{
/*
* Please note: We rely on the runtime loading the profiler with
* 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);
* 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);
}
sample->count = 0;
- mono_stack_walk_async_safe (&async_walk_stack, context, sample);
+ mono_stack_walk_async_safe (&async_walk_stack, (void *) context, sample);
sample->time = current_time ();
sample->tid = thread_id ();
if (++i == hsize)
i = 0;
} while (i != start_pos);
- /* should not happen */
- printf ("failed code page store\n");
+ g_assert_not_reached ();
return 0;
}
//#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;
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;
memcpy (logbuffer->cursor, name, len);
logbuffer->cursor += len;
- EXIT_LOG_EXPLICIT (DO_SEND);
+ EXIT_LOG;
}
/* ELF code crashes on some systems. */
#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) {
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);
}
}
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);
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;
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;
}
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 ||
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;
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);
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;
}
}
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;
sym = symbol_for (addr);
if (sym && sym == last_symbol)
continue;
- 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);
- }
- }
-}
-
-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;
+ last_symbol = sym;
+ if (!sym)
+ continue;
+ dump_usym (sym, addr, 0); /* let's not guess the size */
+ }
+ }
+}
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) {
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
}
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;
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;
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)
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;
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 */ +
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;
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;
LEB128_SIZE /* len */
;
- for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+ for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
if (pcagent->emitted)
continue;
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;
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
{
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;
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 *entered_methods = 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;
}
static void
-obtain_coverage_for_method (MonoProfiler *prof, const MonoProfileCoverageEntry *entry)
+obtain_coverage_for_method (MonoProfiler *prof, const MonoProfilerCoverageData *entry)
{
- int offset = entry->iloffset - previous_offset;
+ int offset = entry->il_offset - log_profiler.coverage_previous_offset;
CoverageEntry *e = g_new (CoverageEntry, 1);
- previous_offset = entry->iloffset;
+ log_profiler.coverage_previous_offset = entry->il_offset;
e->offset = offset;
e->counter = entry->counter;
- e->filename = g_strdup(entry->filename ? entry->filename : "");
+ e->filename = g_strdup(entry->file_name ? entry->file_name : "");
e->line = entry->line;
- e->column = entry->col;
+ e->column = entry->column;
- g_ptr_array_add (coverage_data, e);
+ g_ptr_array_add (log_profiler.coverage_data, e);
}
static char *
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_coverage_get (prof, 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);
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 = "";
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 */ +
);
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 */
emit_uvalue (logbuffer, fully_covered);
emit_uvalue (logbuffer, partially_covered);
- EXIT_LOG_EXPLICIT (DO_SEND);
+ EXIT_LOG;
g_free (class_name);
}
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)
emit_uvalue (logbuffer, fully_covered);
emit_uvalue (logbuffer, partially_covered);
- EXIT_LOG_EXPLICIT (DO_SEND);
-}
-
-static void
-dump_coverage (MonoProfiler *prof)
-{
- 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");)
+ EXIT_LOG;
}
static void
-process_method_enter_coverage (MonoProfiler *prof, MonoMethod *method)
+dump_coverage (void)
{
- MonoClass *klass;
- MonoImage *image;
-
- if (!coverage_initialized)
- return;
-
- klass = mono_method_get_class (method);
- image = mono_class_get_image (klass);
-
- if (mono_conc_hashtable_lookup (suppressed_assemblies, (gpointer) mono_image_get_name (image)))
- return;
-
- mono_os_mutex_lock (&coverage_mutex);
- mono_conc_hashtable_insert (entered_methods, method, method);
- mono_os_mutex_unlock (&coverage_mutex);
+ 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 *
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;
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);
// 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);
// 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);
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);
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)));
}
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);
- entered_methods = 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
}
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);
}
* 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);
*/
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
*/
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?");
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 (entered_methods);
- 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*
* 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);
}
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));
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);
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 ();
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;
}
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)
}
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);
}
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);
}
}
}
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;
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.
/*
* 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;
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);
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);
}
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);
}
}
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;
ENTER_LOG (&sample_hits_ctr, logbuffer,
EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
LEB128_SIZE /* tid */ +
LEB128_SIZE /* count */ +
1 * (
);
emit_event_time (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT, sample->time);
- emit_byte (logbuffer, SAMPLE_CYCLES);
emit_ptr (logbuffer, (void *) sample->tid);
emit_value (logbuffer, 1);
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;
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);
}
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);
}
}
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);
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);
}
}
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
/*
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 (do_coverage)
- coverage_init (log_profiler);
- log_profiler->coverage_filters = filters;
-
- log_profiler->startup_time = current_time ();
-}
-
-/*
- * declaration to silence the compiler: this is the entry point that
- * mono will load from the shared library and call.
- */
-extern void
-mono_profiler_startup (const char *desc);
+ if (log_config.collect_coverage)
+ coverage_init ();
-extern void
-mono_profiler_startup_log (const char *desc);
+ log_profiler.coverage_filters = filters;
-/*
- * this is the entry point that will be used when the profiler
- * is embedded inside the main executable.
- */
-void
-mono_profiler_startup_log (const char *desc)
-{
- mono_profiler_startup (desc);
+ log_profiler.startup_time = current_time ();
}
+MONO_API void
+mono_profiler_init_log (const char *desc);
+
void
-mono_profiler_startup (const char *desc)
+mono_profiler_init_log (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;
- only_coverage = config.only_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);
}
}
PROF_TLS_INIT ();
- create_profiler (desc, config.output_filename, filters);
+ create_profiler (desc, log_config.output_filename, filters);
+
+ mono_lls_init (&log_profiler.profiler_thread_list, NULL);
- mono_lls_init (&profiler_thread_list, NULL);
+ MonoProfilerHandle handle = log_profiler.handle = mono_profiler_install (&log_profiler);
- //This two events are required for the profiler to work
- int events = MONO_PROFILE_THREADS | MONO_PROFILE_GC;
+ /*
+ * 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.
+ */
- //Required callbacks
- mono_profiler_install (log_profiler, log_shutdown);
- mono_profiler_install_runtime_initialized (runtime_initialized);
+ 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_install_gc (gc_event, gc_resize);
- mono_profiler_install_thread (thread_start, thread_end);
+ mono_profiler_set_gc_event_callback (handle, gc_event);
- //It's questionable whether we actually want this to be mandatory, maybe put it behind the actual event?
- mono_profiler_install_thread_name (thread_name);
+ mono_profiler_set_thread_started_callback (handle, thread_start);
+ mono_profiler_set_thread_stopped_callback (handle, thread_end);
+ mono_profiler_set_thread_name_callback (handle, thread_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_DOMAIN_EVENTS) {
- events |= MONO_PROFILE_APPDOMAIN_EVENTS;
- mono_profiler_install_appdomain (NULL, domain_loaded, domain_unloaded, NULL);
- mono_profiler_install_appdomain_name (domain_name);
- }
+ mono_profiler_set_context_loaded_callback (handle, context_loaded);
+ mono_profiler_set_context_unloaded_callback (handle, context_unloaded);
- if (config.effective_mask & PROFLOG_ASSEMBLY_EVENTS) {
- events |= MONO_PROFILE_ASSEMBLY_EVENTS;
- mono_profiler_install_assembly (NULL, assembly_loaded, assembly_unloaded, NULL);
- }
+ mono_profiler_set_assembly_loaded_callback (handle, assembly_loaded);
+ mono_profiler_set_assembly_unloading_callback (handle, assembly_unloaded);
- if (config.effective_mask & PROFLOG_MODULE_EVENTS) {
- events |= MONO_PROFILE_MODULE_EVENTS;
- mono_profiler_install_module (NULL, image_loaded, image_unloaded, NULL);
- }
+ mono_profiler_set_image_loaded_callback (handle, image_loaded);
+ mono_profiler_set_image_unloading_callback (handle, image_unloaded);
- if (config.effective_mask & PROFLOG_CLASS_EVENTS) {
- events |= MONO_PROFILE_CLASS_EVENTS;
- mono_profiler_install_class (NULL, class_loaded, NULL, NULL);
- }
+ mono_profiler_set_class_loaded_callback (handle, class_loaded);
- if (config.effective_mask & PROFLOG_JIT_COMPILATION_EVENTS) {
- events |= MONO_PROFILE_JIT_COMPILATION;
- mono_profiler_install_jit_end (method_jitted);
- mono_profiler_install_code_buffer_new (code_buffer_new);
- }
+ mono_profiler_set_jit_done_callback (handle, method_jitted);
- if (config.effective_mask & PROFLOG_EXCEPTION_EVENTS) {
- events |= MONO_PROFILE_EXCEPTIONS;
- mono_profiler_install_exception (throw_exc, method_exc_leave, NULL);
- mono_profiler_install_exception_clause (clause_exc);
+ 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) {
- events |= MONO_PROFILE_ALLOCATIONS;
- mono_profiler_install_allocation (gc_alloc);
+ 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);
}
- //PROFLOG_GC_EVENTS is mandatory
- //PROFLOG_THREAD_EVENTS is mandatory
+ if (ENABLED (PROFLOG_GC_EVENTS))
+ mono_profiler_set_gc_resize_callback (handle, gc_resize);
- if (config.effective_mask & PROFLOG_CALL_EVENTS) {
- events |= MONO_PROFILE_ENTER_LEAVE;
- mono_profiler_install_enter_leave (method_enter, method_leave);
- }
+ if (ENABLED (PROFLOG_GC_ALLOCATION_EVENTS))
+ mono_profiler_set_gc_allocation_callback (handle, gc_alloc);
- if (config.effective_mask & PROFLOG_INS_COVERAGE_EVENTS) {
- events |= MONO_PROFILE_INS_COVERAGE;
- mono_profiler_install_coverage_filter (coverage_filter);
- }
+ if (ENABLED (PROFLOG_GC_MOVE_EVENTS))
+ mono_profiler_set_gc_moves_callback (handle, gc_moves);
- //XXX should we check for PROFLOG_SAMPLING_FEATURE instead??
- if (config.effective_mask & PROFLOG_SAMPLING_EVENTS) {
- events |= MONO_PROFILE_STATISTICAL;
- mono_profiler_set_statistical_mode (config.sampling_mode, config.sample_freq);
- mono_profiler_install_statistical (mono_sample_hit);
- }
+ if (ENABLED (PROFLOG_GC_ROOT_EVENTS))
+ mono_profiler_set_gc_roots_callback (handle, gc_roots);
- if (config.effective_mask & PROFLOG_MONITOR_EVENTS) {
- events |= MONO_PROFILE_MONITOR_EVENTS;
- mono_profiler_install_monitor (monitor_event);
+ 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_GC_MOVES_EVENTS) {
- events |= MONO_PROFILE_GC_MOVES;
- mono_profiler_install_gc_moves (gc_moves);
+ 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);
}
- // TODO split those in two profiler events
- if (config.effective_mask & (PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_HANDLE_EVENTS)) {
- events |= MONO_PROFILE_GC_ROOTS;
- mono_profiler_install_gc_roots (
- config.effective_mask & (PROFLOG_GC_HANDLE_EVENTS) ? gc_handle : NULL,
- (config.effective_mask & PROFLOG_GC_ROOT_EVENTS) ? gc_roots : NULL);
- }
+ //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_CONTEXT_EVENTS) {
- events |= MONO_PROFILE_CONTEXT_EVENTS;
- mono_profiler_install_context (context_loaded, context_unloaded);
- }
+ if (ENABLED (PROFLOG_SAMPLE_EVENTS))
+ mono_profiler_set_sample_hit_callback (handle, mono_sample_hit);
- if (config.effective_mask & PROFLOG_FINALIZATION_EVENTS) {
- events |= MONO_PROFILE_GC_FINALIZATION;
- mono_profiler_install_gc_finalize (finalize_begin, finalize_object_begin, finalize_object_end, finalize_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
- events |= MONO_PROFILE_GC_FINALIZATION;
- mono_profiler_install_gc_finalize (NULL, NULL, NULL, finalize_end);
+ 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);
}
- //PROFLOG_COUNTER_EVENTS is a pseudo event controled by the no_counters global var
- //PROFLOG_GC_HANDLE_EVENTS is handled together with PROFLOG_GC_ROOT_EVENTS
+ if (log_config.collect_coverage)
+ mono_profiler_set_coverage_filter_callback (handle, coverage_filter);
+
+ mono_profiler_enable_allocations ();
+ mono_profiler_enable_sampling (handle);
- mono_profiler_set_events ((MonoProfileFlags)events);
+ /*
+ * 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.");
}
#define __MONO_PROFLOG_H__
#include <glib.h>
+#define MONO_PROFILER_UNSTABLE_GC_ROOTS
#include <mono/metadata/profiler.h>
#define BUF_ID 0x4D504C01
added an image pointer field to assembly load events
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 {
TYPE_COVERAGE_CLASS = 3 << 4,
/* extended type for TYPE_META */
TYPE_SYNC_POINT = 0 << 4,
- TYPE_END
};
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;
-// Sampling sources
-// Unless you have compiled with --enable-perf-events, only SAMPLE_CYCLES is available
+typedef enum {
+ MONO_PROFILER_MONITOR_CONTENTION = 1,
+ MONO_PROFILER_MONITOR_DONE = 2,
+ MONO_PROFILER_MONITOR_FAIL = 3,
+} MonoProfilerMonitorEvent;
+
enum {
- SAMPLE_CYCLES = 1,
- SAMPLE_INSTRUCTIONS,
- SAMPLE_CACHE_MISSES,
- SAMPLE_CACHE_REFS,
- SAMPLE_BRANCHES,
- SAMPLE_BRANCH_MISSES,
- SAMPLE_LAST
+ 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_GC_EVENTS | PROFLOG_THREAD_EVENTS | PROFLOG_CALL_EVENTS | 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;
-
- //If true, emit coverage but don't emit enter/exit events - this happens cuz they share an event
- gboolean only_coverage;
+ // 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
//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;
- MonoProfileSamplingMode sampling_mode;
+ // Sample mode. Only used at startup.
+ MonoProfilerSampleMode sampling_mode;
} ProfilerConfig;
void proflog_parse_args (ProfilerConfig *config, const char *desc);
return NULL;
}
+// For backwards compatibility.
+enum {
+ SAMPLE_CYCLES = 1,
+ SAMPLE_INSTRUCTIONS,
+ SAMPLE_CACHE_MISSES,
+ SAMPLE_CACHE_REFS,
+ SAMPLE_BRANCHES,
+ 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)
{
}
obj = hs->objects_hash [oi];
cd = obj->hklass;
- if (hs->roots_types [i] & MONO_PROFILE_GC_ROOT_PINNING)
+ if (hs->roots_types [i] & MONO_PROFILER_GC_ROOT_PINNING)
cd->pinned_references++;
cd->root_references++;
}
static const char*
get_root_name (int rtype)
{
- switch (rtype & MONO_PROFILE_GC_ROOT_TYPEMASK) {
- case MONO_PROFILE_GC_ROOT_STACK: return "stack";
- case MONO_PROFILE_GC_ROOT_FINALIZER: return "finalizer";
- case MONO_PROFILE_GC_ROOT_HANDLE: return "handle";
- case MONO_PROFILE_GC_ROOT_OTHER: return "other";
- case MONO_PROFILE_GC_ROOT_MISC: return "misc";
+ switch (rtype & MONO_PROFILER_GC_ROOT_TYPEMASK) {
+ case MONO_PROFILER_GC_ROOT_STACK: return "stack";
+ case MONO_PROFILER_GC_ROOT_FINALIZER: return "finalizer";
+ case MONO_PROFILER_GC_ROOT_HANDLE: return "handle";
+ case MONO_PROFILER_GC_ROOT_OTHER: return "other";
+ case MONO_PROFILER_GC_ROOT_MISC: return "misc";
default: return "unknown";
}
}
uint64_t tdiff = decode_uleb128 (p + 1, &p);
LOG_TIME (time_base, tdiff);
time_base += tdiff;
- sample_type = *p++;
+ if (ctx->data_version < 14)
+ sample_type = *p++;
+ else
+ sample_type = SAMPLE_CYCLES;
tstamp = time_base;
} else {
sample_type = decode_uleb128 (p + 1, &p);
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});
report_errors ();
}
# test traces
-$report = run_test ("test-traces.exe", "legacy,calls,alloc,output=-traces.mlpd", "--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[])"],
);
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,
while (@desc) {
my $dm = pop @desc;
my $fm = pop @frames;
- $fm = pop @frames if $fm =~ /wrapper/;
- push @errors, "Wrong frame $fm for alloc of $type." unless $dm eq $fm;
+ while ($fm =~ /wrapper/) {
+ $fm = pop @frames;
+ }
+ push @errors, "Wrong frame $fm for alloc of $type (expected $dm)." unless $dm eq $fm;
}
} else {
push @errors, "No alloc frames for $type.";
/*
- * mono-codeanalyst.c: VTune profiler
+ * vtune.c: VTune profiler
*
* Author:
* Virgile Bello (virgile.bello@gmail.com)
}
static void
-method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
- if (result == MONO_PROFILE_OK) {
- int i;
- MonoDebugSourceLocation *sourceLoc;
- MonoDebugMethodJitInfo *dmji;
- MonoClass *klass = mono_method_get_class (method);
- char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
- char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature);
- char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass));
- gpointer code_start = mono_jit_info_get_code_start (jinfo);
- int code_size = mono_jit_info_get_code_size (jinfo);
-
- iJIT_Method_Load vtuneMethod;
- memset(&vtuneMethod, 0, sizeof(vtuneMethod));
- vtuneMethod.method_id = iJIT_GetNewMethodID();
- vtuneMethod.method_name = name;
- vtuneMethod.method_load_address = code_start;
- vtuneMethod.method_size = code_size;
- vtuneMethod.class_file_name = classname;
-
- dmji = mono_debug_find_method (method, mono_domain_get());
-
- if (dmji != NULL)
- {
- vtuneMethod.line_number_size = dmji->num_line_numbers;
- vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ?
- (LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL;
+method_jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo)
+{
+ int i;
+ MonoDebugSourceLocation *sourceLoc;
+ MonoDebugMethodJitInfo *dmji;
+ MonoClass *klass = mono_method_get_class (method);
+ char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
+ char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature);
+ char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass));
+ gpointer code_start = mono_jit_info_get_code_start (jinfo);
+ int code_size = mono_jit_info_get_code_size (jinfo);
- for (i = 0; i < dmji->num_line_numbers; ++i)
+ iJIT_Method_Load vtuneMethod;
+ memset(&vtuneMethod, 0, sizeof(vtuneMethod));
+ vtuneMethod.method_id = iJIT_GetNewMethodID();
+ vtuneMethod.method_name = name;
+ vtuneMethod.method_load_address = code_start;
+ vtuneMethod.method_size = code_size;
+ vtuneMethod.class_file_name = classname;
+
+ dmji = mono_debug_find_method (method, mono_domain_get());
+
+ if (dmji != NULL)
+ {
+ vtuneMethod.line_number_size = dmji->num_line_numbers;
+ vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ?
+ (LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL;
+
+ for (i = 0; i < dmji->num_line_numbers; ++i)
+ {
+ sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
+ if (sourceLoc == NULL)
{
- sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
- if (sourceLoc == NULL)
- {
- g_free (vtuneMethod.line_number_table);
- vtuneMethod.line_number_table = NULL;
- vtuneMethod.line_number_size = 0;
- break;
- }
- if (i == 0)
- vtuneMethod.source_file_name = strdup(sourceLoc->source_file);
- vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset;
- vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row;
- mono_debug_free_source_location (sourceLoc);
+ g_free (vtuneMethod.line_number_table);
+ vtuneMethod.line_number_table = NULL;
+ vtuneMethod.line_number_size = 0;
+ break;
}
- mono_debug_free_method_jit_info (dmji);
+ if (i == 0)
+ vtuneMethod.source_file_name = strdup(sourceLoc->source_file);
+ vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset;
+ vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row;
+ mono_debug_free_source_location (sourceLoc);
}
+ mono_debug_free_method_jit_info (dmji);
+ }
- iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
+ iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
- if (vtuneMethod.source_file_name != NULL)
- g_free (vtuneMethod.source_file_name);
- if (vtuneMethod.line_number_table != NULL)
- g_free (vtuneMethod.line_number_table);
-
- g_free (signature);
- g_free (name);
- g_free (classname);
- }
+ if (vtuneMethod.source_file_name != NULL)
+ g_free (vtuneMethod.source_file_name);
+ if (vtuneMethod.line_number_table != NULL)
+ g_free (vtuneMethod.line_number_table);
+
+ g_free (signature);
+ g_free (name);
+ g_free (classname);
}
static void
/* the entry point */
void
-mono_profiler_startup (const char *desc)
+mono_profiler_init_vtune (const char *desc)
{
iJIT_IsProfilingActiveFlags flags = iJIT_IsProfilingActive();
if (flags == iJIT_SAMPLING_ON)
{
- mono_profiler_install (NULL, codeanalyst_shutdown);
- mono_profiler_install_jit_end (method_jit_result);
- mono_profiler_install_code_buffer_new (code_buffer_new);
- mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+ MonoProfilerHandle handle = mono_profiler_install (NULL);
+ mono_profiler_set_runtime_shutdown_end_callback (handle, codeanalyst_shutdown);
+ mono_profiler_set_jit_done_callback (handle, method_jit_done);
+ mono_profiler_set_jit_code_buffer_callback (handle, code_buffer_new);
}
}
{
SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Sweeping must have finished before freeing blocks");
-#ifdef TARGET_WIN32
+#if defined(HOST_WIN32) || defined(HOST_ORBIS)
/*
* sgen_free_os_memory () asserts in mono_vfree () because windows doesn't like freeing the middle of
* a VirtualAlloc ()-ed block.
#define MIN_MINOR_COLLECTION_ALLOWANCE ((mword)(SGEN_DEFAULT_NURSERY_SIZE * default_allowance_nursery_size_ratio))
static SgenPointerQueue log_entries = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_TEMPORARY);
-static MonoCoopMutex log_entries_mutex;
+static mono_mutex_t log_entries_mutex;
mword total_promoted_size = 0;
mword total_allocated_major = 0;
static void
sgen_add_log_entry (SgenLogEntry *log_entry)
{
- mono_coop_mutex_lock (&log_entries_mutex);
+ mono_os_mutex_lock (&log_entries_mutex);
sgen_pointer_queue_add (&log_entries, log_entry);
- mono_coop_mutex_unlock (&log_entries_mutex);
+ mono_os_mutex_unlock (&log_entries_mutex);
}
void
if (mono_trace_is_traced (G_LOG_LEVEL_INFO, MONO_TRACE_GC)) {
size_t i;
SGEN_ASSERT (0, !sgen_is_world_stopped (), "We can't log if the world is stopped");
- mono_coop_mutex_lock (&log_entries_mutex);
+ mono_os_mutex_lock (&log_entries_mutex);
for (i = 0; i < log_entries.next_slot; i++) {
sgen_output_log_entry (log_entries.data [i], stw_time, generation);
sgen_free_internal (log_entries.data [i], INTERNAL_MEM_LOG_ENTRY);
}
sgen_pointer_queue_clear (&log_entries);
- mono_coop_mutex_unlock (&log_entries_mutex);
+ mono_os_mutex_unlock (&log_entries_mutex);
}
}
mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, (void*)&total_alloc);
mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, (void*)&total_alloc_max);
- mono_coop_mutex_init (&log_entries_mutex);
+ mono_os_mutex_init (&log_entries_mutex);
sgen_register_fixed_internal_mem_type (INTERNAL_MEM_LOG_ENTRY, sizeof (SgenLogEntry));
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)
assemblyresolve_event.cs \
assemblyresolve_event3.cs \
assemblyresolve_event4.cs \
+ assemblyresolve_event5.cs \
checked.cs \
char-isnumber.cs \
field-layout.cs \
bug-389886-3.exe \
constant-division.exe \
dynamic-method-resurrection.exe \
- assembly_append_ordering.exe
+ assembly_append_ordering.exe \
+ assemblyresolve_event5.exe
# Test which needs System.Web support
PROFILE_DISABLED_TESTS += \
MONO_PATH="assemblyresolve_deps:$(CLASS)" $(top_builddir)/runtime/mono-wrapper $(AOT_BUILD_FLAGS) assemblyresolve_asm.dll
assemblyresolve_deps/Test.dll$(PLATFORM_AOT_SUFFIX): assemblyresolve_deps/TestBase.dll$(PLATFORM_AOT_SUFFIX)
+EXTRA_DIST += assemblyresolve_TestBase.cs assemblyresolve_Test.cs assemblyresolve_asm.cs
assemblyresolve_deps:
mkdir -p assemblyresolve_deps
assemblyresolve_deps/TestBase.dll: assemblyresolve_deps $(srcdir)/assemblyresolve_TestBase.cs
assemblyresolve_event4.exe$(PLATFORM_AOT_SUFFIX): assemblyresolve_deps/Test.dll$(PLATFORM_AOT_SUFFIX) assemblyresolve_deps/TestBase.dll$(PLATFORM_AOT_SUFFIX)
assemblyresolve_event4.exe: assemblyresolve_deps/Test.dll assemblyresolve_deps/TestBase.dll
+EXTRA_DIST += assemblyresolve_event5_label.cs assemblyresolve_event5_helper.cs
+assemblyresolve_deps/assemblyresolve_event5_label.dll: assemblyresolve_event5_label.cs assemblyresolve_deps
+ $(MCS) -target:library -out:assemblyresolve_deps/assemblyresolve_event5_label.dll $(srcdir)/assemblyresolve_event5_label.cs
+assemblyresolve_event5_helper.dll: assemblyresolve_event5_helper.cs assemblyresolve_deps/assemblyresolve_event5_label.dll
+ $(MCS) -target:library -out:assemblyresolve_event5_helper.dll -r:assemblyresolve_deps/assemblyresolve_event5_label.dll $(srcdir)/assemblyresolve_event5_helper.cs
+assemblyresolve_event5.exe: assemblyresolve_event5_helper.dll
+
# We use 'test-support-files' to handle an ordering issue between the 'mono/' and 'runtime/' directories
bug-80307.exe: $(srcdir)/bug-80307.cs
$(MCS) -r:$(CLASS)/System.Web.dll -out:$@ $(srcdir)/bug-80307.cs
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
--- /dev/null
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+
+public class TestAssemblyResolveEvent {
+ public static int Main (String[] args) {
+ // Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=57851
+
+ // If the custom attributes of an assembly trigger a
+ // ResolveEventHandler, and that handler returns an
+ // AssemblyBuilder, don't crash.
+ var h = new MockResolver ("assemblyresolve_event5_label");
+ var aName = new AssemblyName ("assemblyresolve_event5_helper");
+ var a = AppDomain.CurrentDomain.Load (aName);
+ var t = a.GetType ("MyClass");
+ h.StartHandling ();
+ var cas = t.GetCustomAttributes (true);
+ h.StopHandling ();
+ return 0;
+ }
+}
+
+
+public class MockResolver {
+ private Assembly mock;
+ private ResolveEventHandler d;
+ private string theName;
+
+ public MockResolver (string theName) {
+ mock = CreateMock (theName);
+ d = new ResolveEventHandler (HandleResolveEvent);
+ this.theName = theName;
+ }
+
+ public void StartHandling () {
+ AppDomain.CurrentDomain.AssemblyResolve += d;
+ }
+
+ public void StopHandling () {
+ AppDomain.CurrentDomain.AssemblyResolve -= d;
+ }
+
+ public Assembly HandleResolveEvent (Object sender, ResolveEventArgs args) {
+ Console.Error.WriteLine ("handling load of {0}", args.Name);
+ if (args.Name.StartsWith (theName))
+ return mock;
+ else
+ return null;
+ }
+
+ private static Assembly CreateMock (string s) {
+ var an = new AssemblyName (s);
+ var ab = AssemblyBuilder.DefineDynamicAssembly (an, AssemblyBuilderAccess.Run);
+ var mb = ab.DefineDynamicModule (an.Name);
+
+ var tb = mb.DefineType ("Foo", TypeAttributes.Public);
+ tb.DefineDefaultConstructor (MethodAttributes.Public);
+ tb.CreateType ();
+
+ return ab;
+ }
+}
--- /dev/null
+using System;
+
+public class SimpleTypedAttribute : Attribute {
+ public SimpleTypedAttribute (Type t) { }
+}
+
+[SimpleTypedAttribute(typeof(Foo))] /* Foo defined in the assemblyresolve_event5_label assembly */
+public class MyClass {
+ public MyClass () { }
+}
--- /dev/null
+using System;
+
+public class Foo {
+ public Foo () { }
+}
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) {
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");
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 {
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) {
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");
mono-mmap-internals.h \
mono-mmap-windows-internals.h \
mono-os-mutex.h \
+ mono-os-mutex.c \
mono-coop-mutex.h \
mono-once.h \
mono-lazy-init.h \
for (; chunk; ) {
dead = chunk;
- mono_profiler_code_chunk_destroy ((gpointer) dead->data);
+ MONO_PROFILER_RAISE (jit_chunk_destroyed, ((mono_byte *) dead->data));
if (code_manager_callbacks.chunk_destroy)
code_manager_callbacks.chunk_destroy ((gpointer)dead->data);
chunk = chunk->next;
chunk->bsize = bsize;
if (code_manager_callbacks.chunk_new)
code_manager_callbacks.chunk_new ((gpointer)chunk->data, chunk->size);
- mono_profiler_code_chunk_new((gpointer) chunk->data, chunk->size);
+ MONO_PROFILER_RAISE (jit_chunk_created, ((mono_byte *) chunk->data, chunk->size));
code_memory_used += chunk_size;
mono_runtime_resource_check_limit (MONO_RESOURCE_JIT_CODE, code_memory_used);
} MonoDl;
-MonoDl* mono_dl_open (const char *name, int flags, char **error_msg) MONO_LLVM_INTERNAL;
+MONO_API MonoDl* mono_dl_open (const char *name, int flags, char **error_msg) MONO_LLVM_INTERNAL;
char* mono_dl_symbol (MonoDl *module, const char *name, void **symbol) MONO_LLVM_INTERNAL;
void mono_dl_close (MonoDl *module) MONO_LLVM_INTERNAL;
void
mono_error_set_invalid_operation (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
+void
+mono_error_set_file_not_found (MonoError *error, const char *msg_format, ...) MONO_ATTR_FORMAT_PRINTF(2,3);
+
void
mono_error_set_exception_instance (MonoError *error, MonoException *exc);
va_end (args);
}
+/**
+ * mono_error_set_file_not_found:
+ *
+ * System.IO.FileNotFoundException
+ */
+void
+mono_error_set_file_not_found (MonoError *oerror, const char *msg_format, ...)
+{
+ va_list args;
+ va_start (args, msg_format);
+ mono_error_set_generic_errorv (oerror, "System.IO", "FileNotFoundException", msg_format, args);
+ va_end (args);
+}
+
void
mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...)
{
*report = NULL;
}
- mono_profiler_iomap (rep, pathname, new_pathname);
+ MONO_PROFILER_RAISE (iomap_report, (rep, pathname, new_pathname));
g_free (rep);
}
DIR *scanning = NULL;
size_t len;
gboolean drive_stripped = FALSE;
- gboolean do_report = (mono_profiler_get_events () & MONO_PROFILE_IOMAP_EVENTS) != 0;
+ gboolean do_report = MONO_PROFILER_ENABLED (iomap_report);
if (IS_PORTABILITY_NONE) {
return(NULL);
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);
void
mono_trace_cleanup (void);
-void
+MONO_API void
mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args);
void
#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
#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
--- /dev/null
+/**
+ * \file
+ * Portability wrappers around POSIX Mutexes
+ *
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2002 Ximian, Inc. (www.ximian.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ *
+ */
+
+#include <config.h>
+
+#if !defined(HOST_WIN32)
+
+#if defined(TARGET_OSX)
+/* So we can use the declaration of pthread_cond_timedwait_relative_np () */
+#undef _XOPEN_SOURCE
+#endif
+#include <pthread.h>
+
+#include "mono-os-mutex.h"
+
+int
+mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
+{
+ struct timespec ts;
+ int res;
+
+ if (timeout_ms == MONO_INFINITE_WAIT) {
+ mono_os_cond_wait (cond, mutex);
+ return 0;
+ }
+
+ /* ms = 10^-3, us = 10^-6, ns = 10^-9 */
+
+ /* This function only seems to be available on 64bit osx */
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) && defined(TARGET_OSX)
+ memset (&ts, 0, sizeof (struct timespec));
+ ts.tv_sec = timeout_ms / 1000;
+ ts.tv_nsec = (timeout_ms % 1000) * 1000 * 1000;
+
+ res = pthread_cond_timedwait_relative_np (cond, mutex, &ts);
+ if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) {
+ g_print ("cond: %p mutex: %p\n", *(gpointer*)cond, *(gpointer*)mutex);
+ g_error ("%s: pthread_cond_timedwait_relative_np failed with \"%s\" (%d) %ld %ld %d", __func__, g_strerror (res), res, ts.tv_sec, ts.tv_nsec, timeout_ms);
+ }
+ return res != 0 ? -1 : 0;
+#else
+#ifdef BROKEN_CLOCK_SOURCE
+ struct timeval tv;
+
+ /* clock_gettime is not supported in MAC OS x */
+ res = gettimeofday (&tv, NULL);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
+
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+#else
+ /* cond is using CLOCK_MONOTONIC as time source */
+ res = clock_gettime (CLOCK_MONOTONIC, &ts);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: clock_gettime failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
+#endif
+
+ ts.tv_sec += timeout_ms / 1000;
+ ts.tv_nsec += (timeout_ms % 1000) * 1000 * 1000;
+ if (ts.tv_nsec >= 1000 * 1000 * 1000) {
+ ts.tv_nsec -= 1000 * 1000 * 1000;
+ ts.tv_sec ++;
+ }
+
+ res = pthread_cond_timedwait (cond, mutex, &ts);
+ if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) {
+ g_print ("cond: %p mutex: %p\n", *(gpointer*)cond, *(gpointer*)mutex);
+ g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d) %ld %ld %d", __func__, g_strerror (res), res, ts.tv_sec, ts.tv_nsec, timeout_ms);
+ }
+ return res != 0 ? -1 : 0;
+#endif /* !HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP */
+}
+
+#endif /* HOST_WIN32 */
g_error ("%s: pthread_cond_wait failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
-static inline int
-mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
-{
-#ifdef BROKEN_CLOCK_SOURCE
- struct timeval tv;
-#endif
- struct timespec ts;
- int res;
-
- if (timeout_ms == MONO_INFINITE_WAIT) {
- mono_os_cond_wait (cond, mutex);
- return 0;
- }
-
- /* ms = 10^-3, us = 10^-6, ns = 10^-9 */
-
-#ifdef BROKEN_CLOCK_SOURCE
- /* clock_gettime is not supported in MAC OS x */
- res = gettimeofday (&tv, NULL);
- if (G_UNLIKELY (res != 0))
- g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
-
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = tv.tv_usec * 1000;
-#else
- /* cond is using CLOCK_MONOTONIC as time source */
- res = clock_gettime (CLOCK_MONOTONIC, &ts);
- if (G_UNLIKELY (res != 0))
- g_error ("%s: clock_gettime failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
-#endif
-
- ts.tv_sec += timeout_ms / 1000;
- ts.tv_nsec += (timeout_ms % 1000) * 1000 * 1000;
- if (ts.tv_nsec >= 1000 * 1000 * 1000) {
- ts.tv_nsec -= 1000 * 1000 * 1000;
- ts.tv_sec ++;
- }
-
- res = pthread_cond_timedwait (cond, mutex, &ts);
- if (G_UNLIKELY (res != 0 && res != ETIMEDOUT))
- g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d) %ld %ld %d", __func__, g_strerror (res), res, ts.tv_sec, ts.tv_nsec, timeout_ms);
-
- return res != 0 ? -1 : 0;
-}
+int
+mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms);
static inline void
mono_os_cond_signal (mono_cond_t *cond)
#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 */
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);
mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
{
pthread_attr_t attr;
+ gint res;
*staddr = NULL;
*stsize = (size_t)-1;
- pthread_getattr_np (pthread_self (), &attr);
- pthread_attr_getstack (&attr, (void**)staddr, stsize);
- pthread_attr_destroy (&attr);
+ res = pthread_attr_init (&attr);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_attr_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
+ res = pthread_getattr_np (pthread_self (), &attr);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_getattr_np failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
+ res = pthread_attr_getstack (&attr, (void**)staddr, stsize);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_attr_getstack failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
+ res = pthread_attr_destroy (&attr);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_attr_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
}
#endif
#elif defined (HAVE_PTHREAD_KILL)
result = pthread_kill (mono_thread_info_get_tid (info), signum);
#else
+ result = -1;
g_error ("pthread_kill () is not supported by this platform");
#endif
-<?xml version="1.0" encoding="utf-8"?>\r
+<?xml version="1.0" encoding="utf-8"?>\r
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
<ItemGroup Label="ProjectConfigurations">\r
<ProjectConfiguration Include="Debug|Win32">\r
<ClCompile Include="..\mono\utils\mono-uri.c" />\r
<ClCompile Include="..\mono\utils\mono-value-hash.c" />\r
<ClCompile Include="..\mono\utils\monobitset.c" />\r
+ <ClCompile Include="..\mono\utils\mono-os-mutex.c" />\r
<ClCompile Include="..\mono\utils\os-event-win32.c" />\r
<ClCompile Include="..\mono\utils\strenc.c" />\r
<ClCompile Include="..\mono\utils\atomic.c" />\r
<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>
<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>
</BuildMacro>
</ItemGroup>
<ItemDefinitionGroup />
-</Project>
\ No newline at end of file
+</Project>
; file generated by create-windef.pl
LIBRARY mono-profiler-vtune.dll
EXPORTS
-mono_profiler_startup
\ No newline at end of file
+mono_profiler_init_vtune
mono_assembly_load_from_full
mono_assembly_load_full
mono_assembly_load_module
+mono_assembly_load_module_checked
mono_assembly_load_reference
mono_assembly_load_references
mono_assembly_load_with_partial_name
mono_class_from_typeref_checked
mono_class_get
mono_class_get_byref_type
+mono_class_get_context
mono_class_get_element_class
mono_class_get_event_token
mono_class_get_events
mono_code_manager_commit
mono_code_manager_destroy
mono_code_manager_init
+mono_code_manager_install_callbacks
mono_code_manager_invalidate
mono_code_manager_new
mono_code_manager_new_dynamic
mono_compile_method
mono_conc_hashtable_destroy
mono_conc_hashtable_foreach
+mono_conc_hashtable_foreach_steal
mono_conc_hashtable_insert
mono_conc_hashtable_lookup
mono_conc_hashtable_new
mono_conc_hashtable_remove
mono_config_cleanup
mono_config_for_assembly
+mono_config_get_cpu
+mono_config_get_os
+mono_config_get_wordsize
mono_config_is_server_mode
mono_config_parse
mono_config_parse_memory
mono_g_hash_table_size
mono_gc_collect
mono_gc_collection_count
+mono_gc_finalize_notify
mono_gc_get_generation
mono_gc_get_heap_size
mono_gc_get_used_size
mono_gc_invoke_finalizers
mono_gc_max_generation
+mono_gc_pending_finalizers
mono_gc_reference_queue_add
mono_gc_reference_queue_free
mono_gc_reference_queue_new
mono_get_void_class
mono_guid_to_string
mono_guid_to_string_minimal
+mono_hazard_pointer_get
mono_image_add_to_name_cache
mono_image_addref
mono_image_close
mono_jit_thread_attach
mono_ldstr
mono_ldtoken
+mono_lls_find
+mono_lls_get_hazardous_pointer_with_mask
+mono_lls_init
+mono_lls_insert
+mono_lls_remove
mono_load_remote_field
mono_load_remote_field_new
mono_loader_register_module
mono_lock_free_queue_node_init
mono_lock_free_queue_node_unpoison
mono_locks_dump
-mono_log_close_logfile
-mono_log_close_syslog
-mono_log_open_logfile
-mono_log_open_syslog
-mono_log_write_logfile
-mono_log_write_syslog
mono_lookup_icall_symbol
mono_lookup_internal_call
mono_lookup_pinvoke_call
mono_md5_get_digest_from_file
mono_md5_init
mono_md5_update
+mono_mem_account_register_counters
+mono_mem_account_type_name
mono_mempool_alloc
mono_mempool_alloc0
mono_mempool_contains_addr
mono_method_desc_search_in_image
mono_method_full_name
mono_method_get_class
+mono_method_get_context
mono_method_get_flags
mono_method_get_generic_container
mono_method_get_header
mono_method_header_get_num_clauses
mono_method_print_code
mono_method_signature
+mono_method_signature_checked
mono_method_verify
mono_mlist_alloc
mono_mlist_append
mono_monitor_exit
mono_monitor_try_enter
mono_mprotect
+mono_native_getrootdir
+mono_native_thread_create
+mono_native_thread_id_equals
mono_native_thread_id_get
+mono_native_thread_join
mono_native_thread_set_name
mono_object_castclass_mbyref
mono_object_clone
mono_print_thread_dump
mono_print_thread_dump_from_ctx
mono_print_unhandled_exception
-mono_profiler_coverage_get
-mono_profiler_get_events
+mono_profiler_enable_allocations
+mono_profiler_enable_sampling
+mono_profiler_get_coverage_data
+mono_profiler_get_sample_mode
mono_profiler_install
-mono_profiler_install_allocation
-mono_profiler_install_appdomain
-mono_profiler_install_appdomain_name
-mono_profiler_install_assembly
-mono_profiler_install_class
-mono_profiler_install_code_buffer_new
-mono_profiler_install_code_chunk_destroy
-mono_profiler_install_code_chunk_new
-mono_profiler_install_context
-mono_profiler_install_coverage_filter
-mono_profiler_install_enter_leave
-mono_profiler_install_exception
-mono_profiler_install_gc
-mono_profiler_install_gc_moves
-mono_profiler_install_gc_roots
-mono_profiler_install_iomap
-mono_profiler_install_jit_compile
-mono_profiler_install_jit_end
-mono_profiler_install_method_free
-mono_profiler_install_method_invoke
-mono_profiler_install_module
-mono_profiler_install_monitor
-mono_profiler_install_runtime_initialized
-mono_profiler_install_statistical
-mono_profiler_install_statistical_call_chain
-mono_profiler_install_thread
-mono_profiler_install_thread_name
-mono_profiler_install_transition
mono_profiler_load
-mono_profiler_set_events
-mono_profiler_set_statistical_mode
+mono_profiler_set_assembly_loaded_callback
+mono_profiler_set_assembly_loading_callback
+mono_profiler_set_assembly_unloaded_callback
+mono_profiler_set_assembly_unloading_callback
+mono_profiler_set_call_instrumentation_filter_callback
+mono_profiler_set_class_failed_callback
+mono_profiler_set_class_loaded_callback
+mono_profiler_set_class_loading_callback
+mono_profiler_set_context_loaded_callback
+mono_profiler_set_context_unloaded_callback
+mono_profiler_set_coverage_filter_callback
+mono_profiler_set_domain_loaded_callback
+mono_profiler_set_domain_loading_callback
+mono_profiler_set_domain_name_callback
+mono_profiler_set_domain_unloaded_callback
+mono_profiler_set_domain_unloading_callback
+mono_profiler_set_exception_clause_callback
+mono_profiler_set_exception_throw_callback
+mono_profiler_set_gc_allocation_callback
+mono_profiler_set_gc_event_callback
+mono_profiler_set_gc_finalized_callback
+mono_profiler_set_gc_finalized_object_callback
+mono_profiler_set_gc_finalizing_callback
+mono_profiler_set_gc_finalizing_object_callback
+mono_profiler_set_gc_handle_created_callback
+mono_profiler_set_gc_handle_deleted_callback
+mono_profiler_set_gc_moves_callback
+mono_profiler_set_gc_resize_callback
+mono_profiler_set_gc_roots_callback
+mono_profiler_set_image_failed_callback
+mono_profiler_set_image_loaded_callback
+mono_profiler_set_image_loading_callback
+mono_profiler_set_image_unloaded_callback
+mono_profiler_set_image_unloading_callback
+mono_profiler_set_iomap_report_callback
+mono_profiler_set_jit_begin_callback
+mono_profiler_set_jit_chunk_created_callback
+mono_profiler_set_jit_chunk_destroyed_callback
+mono_profiler_set_jit_code_buffer_callback
+mono_profiler_set_jit_done_callback
+mono_profiler_set_jit_failed_callback
+mono_profiler_set_method_begin_invoke_callback
+mono_profiler_set_method_end_invoke_callback
+mono_profiler_set_method_enter_callback
+mono_profiler_set_method_exception_leave_callback
+mono_profiler_set_method_free_callback
+mono_profiler_set_method_leave_callback
+mono_profiler_set_monitor_acquired_callback
+mono_profiler_set_monitor_contention_callback
+mono_profiler_set_monitor_failed_callback
+mono_profiler_set_runtime_initialized_callback
+mono_profiler_set_runtime_shutdown_begin_callback
+mono_profiler_set_runtime_shutdown_end_callback
+mono_profiler_set_sample_hit_callback
+mono_profiler_set_sample_mode
+mono_profiler_set_thread_name_callback
+mono_profiler_set_thread_started_callback
+mono_profiler_set_thread_stopped_callback
mono_property_get_flags
mono_property_get_get_method
mono_property_get_name
mono_shared_area_remove
mono_shared_area_unload
mono_signature_explicit_this
+mono_signature_full_name
mono_signature_get_call_conv
mono_signature_get_desc
mono_signature_get_param_count
mono_store_remote_field
mono_store_remote_field_new
mono_string_chars
+mono_string_empty
+mono_string_empty_wrapper
mono_string_equal
mono_string_from_bstr
mono_string_from_utf16
mono_string_intern
mono_string_is_interned
mono_string_length
-mono_string_empty
-mono_string_empty_wrapper
mono_string_new
mono_string_new_len
mono_string_new_size
mono_thread_get_managed_id
mono_thread_get_name_utf8
mono_thread_get_undeniable_exception
+mono_thread_hazardous_queue_free
mono_thread_hazardous_try_free
+mono_thread_hazardous_try_free_all
mono_thread_info_detach
+mono_thread_info_get_small_id
+mono_thread_info_register_small_id
+mono_thread_info_yield
mono_thread_init
mono_thread_is_foreign
mono_thread_manage
mono_threads_set_default_stacksize
mono_trace_set_level_string
mono_trace_set_log_handler
-mono_trace_set_logdest_string
-mono_trace_set_logheader_string
mono_trace_set_mask_string
mono_trace_set_print_handler
mono_trace_set_printerr_handler
mono_type_get_underlying_type
mono_type_is_byref
mono_type_is_pointer
+mono_type_is_primitive
mono_type_is_reference
mono_type_is_struct
mono_type_is_valid_enum_basetype
mono_utf8_validate_and_len_with_bounds
mono_valloc
mono_valloc_aligned
+mono_valloc_granule
mono_value_box
mono_value_copy
mono_value_copy_array
mono_assembly_load_from_full
mono_assembly_load_full
mono_assembly_load_module
+mono_assembly_load_module_checked
mono_assembly_load_reference
mono_assembly_load_references
mono_assembly_load_with_partial_name
mono_class_from_typeref_checked
mono_class_get
mono_class_get_byref_type
+mono_class_get_context
mono_class_get_element_class
mono_class_get_event_token
mono_class_get_events
mono_code_manager_commit
mono_code_manager_destroy
mono_code_manager_init
+mono_code_manager_install_callbacks
mono_code_manager_invalidate
mono_code_manager_new
mono_code_manager_new_dynamic
mono_compile_method
mono_conc_hashtable_destroy
mono_conc_hashtable_foreach
+mono_conc_hashtable_foreach_steal
mono_conc_hashtable_insert
mono_conc_hashtable_lookup
mono_conc_hashtable_new
mono_conc_hashtable_remove
mono_config_cleanup
mono_config_for_assembly
+mono_config_get_cpu
+mono_config_get_os
+mono_config_get_wordsize
mono_config_is_server_mode
mono_config_parse
mono_config_parse_memory
mono_g_hash_table_size
mono_gc_collect
mono_gc_collection_count
+mono_gc_finalize_notify
mono_gc_get_generation
mono_gc_get_heap_size
mono_gc_get_used_size
mono_gc_invoke_finalizers
mono_gc_max_generation
+mono_gc_pending_finalizers
mono_gc_reference_queue_add
mono_gc_reference_queue_free
mono_gc_reference_queue_new
mono_get_void_class
mono_guid_to_string
mono_guid_to_string_minimal
+mono_hazard_pointer_get
mono_image_add_to_name_cache
mono_image_addref
mono_image_close
mono_jit_thread_attach
mono_ldstr
mono_ldtoken
+mono_lls_find
+mono_lls_get_hazardous_pointer_with_mask
+mono_lls_init
+mono_lls_insert
+mono_lls_remove
mono_load_remote_field
mono_load_remote_field_new
mono_loader_register_module
mono_lock_free_queue_node_init
mono_lock_free_queue_node_unpoison
mono_locks_dump
-mono_log_close_logfile
-mono_log_close_syslog
-mono_log_open_logfile
-mono_log_open_syslog
-mono_log_write_logfile
-mono_log_write_syslog
mono_lookup_icall_symbol
mono_lookup_internal_call
mono_lookup_pinvoke_call
mono_md5_get_digest_from_file
mono_md5_init
mono_md5_update
+mono_mem_account_register_counters
+mono_mem_account_type_name
mono_mempool_alloc
mono_mempool_alloc0
mono_mempool_contains_addr
mono_method_desc_search_in_image
mono_method_full_name
mono_method_get_class
+mono_method_get_context
mono_method_get_flags
mono_method_get_generic_container
mono_method_get_header
mono_method_header_get_num_clauses
mono_method_print_code
mono_method_signature
+mono_method_signature_checked
mono_method_verify
mono_mlist_alloc
mono_mlist_append
mono_monitor_exit
mono_monitor_try_enter
mono_mprotect
+mono_native_getrootdir
+mono_native_thread_create
+mono_native_thread_id_equals
mono_native_thread_id_get
+mono_native_thread_join
mono_native_thread_set_name
mono_object_castclass_mbyref
mono_object_clone
mono_print_thread_dump
mono_print_thread_dump_from_ctx
mono_print_unhandled_exception
-mono_profiler_coverage_get
-mono_profiler_get_events
+mono_profiler_enable_allocations
+mono_profiler_enable_sampling
+mono_profiler_get_coverage_data
+mono_profiler_get_sample_mode
mono_profiler_install
-mono_profiler_install_allocation
-mono_profiler_install_appdomain
-mono_profiler_install_appdomain_name
-mono_profiler_install_assembly
-mono_profiler_install_class
-mono_profiler_install_code_buffer_new
-mono_profiler_install_code_chunk_destroy
-mono_profiler_install_code_chunk_new
-mono_profiler_install_context
-mono_profiler_install_coverage_filter
-mono_profiler_install_enter_leave
-mono_profiler_install_exception
-mono_profiler_install_gc
-mono_profiler_install_gc_moves
-mono_profiler_install_gc_roots
-mono_profiler_install_iomap
-mono_profiler_install_jit_compile
-mono_profiler_install_jit_end
-mono_profiler_install_method_free
-mono_profiler_install_method_invoke
-mono_profiler_install_module
-mono_profiler_install_monitor
-mono_profiler_install_runtime_initialized
-mono_profiler_install_statistical
-mono_profiler_install_statistical_call_chain
-mono_profiler_install_thread
-mono_profiler_install_thread_name
-mono_profiler_install_transition
mono_profiler_load
-mono_profiler_set_events
-mono_profiler_set_statistical_mode
+mono_profiler_set_assembly_loaded_callback
+mono_profiler_set_assembly_loading_callback
+mono_profiler_set_assembly_unloaded_callback
+mono_profiler_set_assembly_unloading_callback
+mono_profiler_set_call_instrumentation_filter_callback
+mono_profiler_set_class_failed_callback
+mono_profiler_set_class_loaded_callback
+mono_profiler_set_class_loading_callback
+mono_profiler_set_context_loaded_callback
+mono_profiler_set_context_unloaded_callback
+mono_profiler_set_coverage_filter_callback
+mono_profiler_set_domain_loaded_callback
+mono_profiler_set_domain_loading_callback
+mono_profiler_set_domain_name_callback
+mono_profiler_set_domain_unloaded_callback
+mono_profiler_set_domain_unloading_callback
+mono_profiler_set_exception_clause_callback
+mono_profiler_set_exception_throw_callback
+mono_profiler_set_gc_allocation_callback
+mono_profiler_set_gc_event_callback
+mono_profiler_set_gc_finalized_callback
+mono_profiler_set_gc_finalized_object_callback
+mono_profiler_set_gc_finalizing_callback
+mono_profiler_set_gc_finalizing_object_callback
+mono_profiler_set_gc_handle_created_callback
+mono_profiler_set_gc_handle_deleted_callback
+mono_profiler_set_gc_moves_callback
+mono_profiler_set_gc_resize_callback
+mono_profiler_set_gc_roots_callback
+mono_profiler_set_image_failed_callback
+mono_profiler_set_image_loaded_callback
+mono_profiler_set_image_loading_callback
+mono_profiler_set_image_unloaded_callback
+mono_profiler_set_image_unloading_callback
+mono_profiler_set_iomap_report_callback
+mono_profiler_set_jit_begin_callback
+mono_profiler_set_jit_chunk_created_callback
+mono_profiler_set_jit_chunk_destroyed_callback
+mono_profiler_set_jit_code_buffer_callback
+mono_profiler_set_jit_done_callback
+mono_profiler_set_jit_failed_callback
+mono_profiler_set_method_begin_invoke_callback
+mono_profiler_set_method_end_invoke_callback
+mono_profiler_set_method_enter_callback
+mono_profiler_set_method_exception_leave_callback
+mono_profiler_set_method_free_callback
+mono_profiler_set_method_leave_callback
+mono_profiler_set_monitor_acquired_callback
+mono_profiler_set_monitor_contention_callback
+mono_profiler_set_monitor_failed_callback
+mono_profiler_set_runtime_initialized_callback
+mono_profiler_set_runtime_shutdown_begin_callback
+mono_profiler_set_runtime_shutdown_end_callback
+mono_profiler_set_sample_hit_callback
+mono_profiler_set_sample_mode
+mono_profiler_set_thread_name_callback
+mono_profiler_set_thread_started_callback
+mono_profiler_set_thread_stopped_callback
mono_property_get_flags
mono_property_get_get_method
mono_property_get_name
mono_shared_area_remove
mono_shared_area_unload
mono_signature_explicit_this
+mono_signature_full_name
mono_signature_get_call_conv
mono_signature_get_desc
mono_signature_get_param_count
mono_store_remote_field
mono_store_remote_field_new
mono_string_chars
+mono_string_empty
+mono_string_empty_wrapper
mono_string_equal
mono_string_from_bstr
mono_string_from_utf16
mono_string_intern
mono_string_is_interned
mono_string_length
-mono_string_empty
-mono_string_empty_wrapper
mono_string_new
mono_string_new_len
mono_string_new_size
mono_thread_get_managed_id
mono_thread_get_name_utf8
mono_thread_get_undeniable_exception
+mono_thread_hazardous_queue_free
mono_thread_hazardous_try_free
+mono_thread_hazardous_try_free_all
mono_thread_info_detach
+mono_thread_info_get_small_id
+mono_thread_info_register_small_id
+mono_thread_info_yield
mono_thread_init
mono_thread_is_foreign
mono_thread_manage
mono_threads_set_default_stacksize
mono_trace_set_level_string
mono_trace_set_log_handler
-mono_trace_set_logdest_string
-mono_trace_set_logheader_string
mono_trace_set_mask_string
mono_trace_set_print_handler
mono_trace_set_printerr_handler
mono_type_get_underlying_type
mono_type_is_byref
mono_type_is_pointer
+mono_type_is_primitive
mono_type_is_reference
mono_type_is_struct
mono_type_is_valid_enum_basetype
mono_utf8_validate_and_len_with_bounds
mono_valloc
mono_valloc_aligned
+mono_valloc_granule
mono_value_box
mono_value_copy
mono_value_copy_array
</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
</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
<Filter>Resource Files</Filter>\r
</None>\r
</ItemGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
class MSBuild (GitHubPackage):
def __init__ (self):
GitHubPackage.__init__ (self, 'mono', 'msbuild', '15.3',
- revision = 'f7dcc3900c808775adad970f047202b4de34e986',
- git_branch = 'xplat-master')
+ revision = '9fcd43ddc7c2f9b250b0d7e823ae01862246b35a')
def build (self):
self.sh ('./cibuild.sh --scope Compile --target Mono --host Mono --config Release')
def __init__(self):
Package.__init__(self, 'mono-extensions', None,
sources=['git@github.com:xamarin/mono-extensions.git'],
- git_branch=self.profile.release_packages[
- 'mono'].git_branch,
revision='07ad37d63e0e9dcf7c879a72bc14c5d6c794f7b6'
)
self.source_dir_name = 'mono-extensions'
- # Mono pull requests won't have mono-extensions branches
- if not self.git_branch or 'pull/' in self.git_branch:
- warn('Using master branch for mono_extensions')
- self.git_branch = 'master'
-
def build(self):
pass
mkdir -p ${REPODIR}
report "Downloading Xar"
wget --quiet -O ${REPODIR}/xar.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/xar/xar-1.5.2.tar.gz || error "*** Could not download Xar ***"
+ report "Downloading x64 hostfxr.dll"
+ wget --quiet -O ${REPODIR}/hostfxr-x64.zip https://www.nuget.org/api/v2/package/runtime.win-x64.Microsoft.NETCore.DotNetHostResolver/2.0.0-preview2-25407-01 || error "*** Could not download 64bit hostfxr.dll ***"
+ report "Downloading x86 hostfxr.dll"
+ wget --quiet -O ${REPODIR}/hostfxr-x86.zip https://www.nuget.org/api/v2/package/runtime.win-x86.Microsoft.NETCore.DotNetHostResolver/2.0.0-preview2-25407-01 || error "*** Could not download 64bit hostfxr.dll ***"
report "Copying Mono MDK for Mac"
cp $1 ${REPODIR}/mono.xar
}
report "Deleting interstitial output"
rm -rf ${REPODIR}/mono-mac \
${REPODIR}/xar \
+ ${REPODIR}/hostfxr-x64 \
+ ${REPODIR}/hostfxr-x86 \
${REPODIR}/Distribution \
${REPODIR}/mono.pkg \
${REPODIR}/Resources \
make
popd
fi
+ report "Unpacking x64 hostfxr.dll"
+ mkdir -p hostfxr-x64
+ unzip -j "${REPODIR}/hostfxr-x64.zip" "runtimes/win-x64/native/hostfxr.dll" -d "hostfxr-x64"
+ report "Unpacking x86 hostfxr.dll"
+ mkdir -p hostfxr-x86
+ unzip -j "${REPODIR}/hostfxr-x86.zip" "runtimes/win-x86/native/hostfxr.dll" -d "hostfxr-x86"
report "Unpacking Mono for Mac"
xar/src/xar -x -f mono.xar
zcat mono.pkg/Payload | bsdcpio -i
rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/Microsoft* ${REPODIR}/../../tmp/mono/lib/mono/
rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/msbuild ${REPODIR}/../../tmp/mono/lib/mono/
rm -f ${REPODIR}/../../tmp/mono/lib/mono/msbuild/15.0/bin/SdkResolvers/Microsoft.DotNet.MSBuildSdkResolver/libhostfxr.dylib
+ if [ "$1" = "x64" ]; then
+ cp ${REPODIR}/hostfxr-x64/hostfxr.dll ${REPODIR}/../../tmp/mono/lib/mono/msbuild/15.0/bin/SdkResolvers/Microsoft.DotNet.MSBuildSdkResolver/
+ else
+ cp ${REPODIR}/hostfxr-x86/hostfxr.dll ${REPODIR}/../../tmp/mono/lib/mono/msbuild/15.0/bin/SdkResolvers/Microsoft.DotNet.MSBuildSdkResolver/
+ fi
rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/nuget ${REPODIR}/../../tmp/mono/lib/mono/
rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/xbuild-frameworks ${REPODIR}/../../tmp/mono/lib/mono/
rsync -a --copy-links ${REPODIR}/mono-mac/lib/mono/xbuild/Microsoft/NuGet/Microsoft.NuGet* ${REPODIR}/../../tmp/mono/lib/mono/xbuild/ # note: we can't copy the symlink in xbuild/ so we copy the file it points to
which bsdcpio 2>/dev/null || error "*** bsdcpio is not in \$PATH ***"
which wget 2>/dev/null || error "*** wget is not in \$PATH ***"
which xml2-config 2>/dev/null || error "*** xml2-config is not in \$PATH ***"
+ which unzip 2>/dev/null || error "*** unzip is not in \$PATH ***"
if [ ! -e "/usr/include/openssl/crypto.h" ]
then error "*** openssl-devel is not installed ***"
fi
for i in ${COMPONENTS}
do defs/$i clean
defs/$i build
- defs/$i install
+ defs/$i install "x86"
done
resources/build.bat
for i in ${COMPONENTS}
do defs/$i clean
defs/$i build
- defs/$i install
+ defs/$i install "x64"
done
resources/build64.bat
build_profiles += orbis
endif
+if INSTALL_UNREAL
+build_profiles += unreal
+endif
+
test_profiles = $(build_profiles)
if BUILD_MCS
{
}
+static MonoProfilerCallInstrumentationFlags
+sample_instrumentation_filter (MonoProfiler *prof, MonoMethod *method)
+{
+ return MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+}
+
/* the entry point */
void
-mono_profiler_startup (const char *desc)
+mono_profiler_init_sample (const char *desc)
{
MonoProfiler *prof;
prof = g_new0 (MonoProfiler, 1);
- mono_profiler_install (prof, sample_shutdown);
-
- mono_profiler_install_enter_leave (sample_method_enter, sample_method_leave);
-
- mono_profiler_set_events (MONO_PROFILE_ENTER_LEAVE);
+ MonoProfilerHandle handle = mono_profiler_install (prof);
+ mono_profiler_set_runtime_shutdown_callback (handle, sample_shutdown);
+ mono_profiler_set_call_instrumentation_filter_callback (handle, sample_instrumentation_filter);
+ mono_profiler_set_method_enter_callback (handle, sample_method_enter);
+ mono_profiler_set_method_leave_callback (handle, sample_method_leave);
}
static int installed = 0;
-void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result)
+void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo)
{
if (installed)
return;
}
void
-mono_profiler_startup (const char *desc)
+mono_profiler_init_size (const char *desc)
{
- mono_profiler_install_jit_end (install_icall);
- mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+ MonoProfilerHandle handle = mono_profiler_install (NULL);
+ mono_profiler_set_jit_done_callback (handle, install_icall);
}
if [[ ${label} == osx-* ]] || [[ ${label} == w* ]]
then ${TESTCMD} --label=Windows.Forms --skip;
else
- if make -C mcs/class/System.Windows.Forms test-simple;
- then ${TESTCMD} --label=Windows.Forms --timeout=5m make -w -C mcs/class/System.Windows.Forms run-test
+ if xvfb-run -a -- make -C mcs/class/System.Windows.Forms test-simple;
+ then ${TESTCMD} --label=Windows.Forms --timeout=5m xvfb-run -a -- make -w -C mcs/class/System.Windows.Forms run-test
else echo "The simple test failed (maybe because of missing X server), skipping test suite." && ${TESTCMD} --label=Windows.Forms --skip; fi
fi
${TESTCMD} --label=System.Data --timeout=5m make -w -C mcs/class/System.Data run-test
#!/bin/bash -e
+export MONO_BABYSITTER_EXTRA_XML=${MONO_REPO_ROOT}/acceptance-tests/profiler-stress/TestResult-profiler-stress.xml
+
${TESTCMD} --label=check-profiler-stress --timeout=24h make -C acceptance-tests check-profiler-stress
static string AndroidNdkPath = @"";
static string MaccoreDir = @"";
static string TargetDir = @"";
+ static bool GenIOS;
public enum TargetPlatform
{
MaccoreDir = Path.Combine (maccoreDir);
}
- if (Directory.Exists(MaccoreDir))
+ if (Directory.Exists(MaccoreDir) || GenIOS)
SetupiOSTargets();
foreach (var target in Targets)
source.Options.AddDefines ("HAVE_SGEN_GC");
source.Options.AddDefines ("HAVE_MOVING_COLLECTOR");
+ source.Options.AddDefines("MONO_GENERATING_OFFSETS");
}
}
{ "android-ndk=", "Path to Android NDK", v => AndroidNdkPath = v },
{ "targetdir=", "Path to the directory containing the mono build", v =>TargetDir = v },
{ "mono=", "include directory", v => MonoDir = v },
+ { "gen-ios", "generate iOS offsets", v => GenIOS = v != null },
{ "h|help", "show this message and exit", v => showHelp = v != null },
};
parserOptions.AddArguments("-xc");
parserOptions.AddArguments("-std=gnu99");
parserOptions.AddDefines("CPPSHARP");
+ parserOptions.AddDefines("MONO_GENERATING_OFFSETS");
foreach (var define in target.Defines)
parserOptions.AddDefines(define);
break;
case TargetPlatform.WatchOS:
case TargetPlatform.iOS: {
- string targetPath = Path.Combine (MaccoreDir, "builds");
- if (!Directory.Exists (MonoDir))
- MonoDir = Path.GetFullPath (Path.Combine (targetPath, "../../mono"));
- targetBuild = Path.Combine(targetPath, target.Build);
+ if (!string.IsNullOrEmpty (TargetDir)) {
+ targetBuild = TargetDir;
+ } else {
+ string targetPath = Path.Combine (MaccoreDir, "builds");
+ if (!Directory.Exists (MonoDir))
+ MonoDir = Path.GetFullPath (Path.Combine (targetPath, "../../mono"));
+ targetBuild = Path.Combine(targetPath, target.Build);
+ }
break;
}
default:
}
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;
}
}