cd $(mcslib) && { (wget -O- $(monolite_url) || curl $(monolite_url)) | gzip -d | tar xf - ; }
cd $(mcslib) && mv -f monolite-* monolite
+if BITCODE
+BITCODE_CHECK=yes
+endif
+
.PHONY: check-ci
check-ci:
- MONO_LLVMONLY=$(MONO_LLVMONLY) $(srcdir)/scripts/ci/run-test-$(TEST_PROFILE).sh
+ MONO_LLVMONLY=$(BITCODE_CHECK) $(srcdir)/scripts/ci/run-test-$(TEST_PROFILE).sh
.PHONY: validate do-build-mono-mcs mcs-do-clean mcs-do-tests
validate: do-build-mono-mcs
sed -i -e 's/\\4.5-api"/\\4.5"/g' $$PREFIX/lib/mono/xbuild-frameworks/.NETFramework/v4.5/RedistList/FrameworkList.xml; \
export MSBuildExtensionsPath=$$PREFIX/lib/mono/xbuild; \
MONO_DOTNET_PORTABLE_DIR=$$PREFIX/lib/mono/xbuild-frameworks/.NETPortable/; \
- MONO_NUGET_TARGETS_DIR=$$PREFIX/lib/mono/xbuild/Microsoft/NuGet/; \
- MONO_PORTABLE_TARGETS_DIR=$$PREFIX/lib/mono/xbuild/Microsoft/Portable/v5.0; \
- if [ ! -d "$$MONO_DOTNET_PORTABLE_DIR/v5.0" ]; then \
+ if [ ! -d "$$MONO_DOTNET_PORTABLE_DIR/v4.6" ]; then \
mkdir -p $$MONO_DOTNET_PORTABLE_DIR; \
- mkdir -p $$MONO_NUGET_TARGETS_DIR; \
- mkdir -p $$MONO_PORTABLE_TARGETS_DIR; \
curl -SL "http://download.mono-project.com/third-party/RoslynBuildDependencies.zip" > /tmp/RoslynBuildDependencies.zip; \
unzip -o /tmp/RoslynBuildDependencies.zip -d /tmp/RoslynBuildDependencies; \
cp -r /tmp/RoslynBuildDependencies/PortableReferenceAssemblies/* $$MONO_DOTNET_PORTABLE_DIR; \
- cp /tmp/RoslynBuildDependencies/NuGetTargets/* $$MONO_NUGET_TARGETS_DIR; \
- cp /tmp/RoslynBuildDependencies/PortableTargets/* $$MONO_PORTABLE_TARGETS_DIR; \
fi; \
cd $(ROSLYN_PATH); \
sed -i -e 'N; s/bootstrapArg=".*\n.*"/bootstrapArg=""/g' cibuild.sh; \
#AC_PREREQ([2.62])
# when bumping version number below, keep it in sync with man/mono.1 too
-AC_INIT(mono, [4.5.2],
+AC_INIT(mono, [4.7.0],
[http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
AC_CONFIG_SRCDIR([README.md])
# We rely on signed overflow to behave
CFLAGS="$CFLAGS -fwrapv"
+ # We rely on zero length arrays in structs
+ CFLAGS="$CFLAGS -Wno-zero-length-array"
+
CFLAGS="$CFLAGS -DMONO_DLL_EXPORT"
if test x"$disable_visibility_hidden" = xno; then
# Don't export any symbols by default
AC_SUBST(INSTALL_MOBILE_STATIC)
-AC_SUBST(BITCODE)
-
default_profile=net_4_x
if test -z "$INSTALL_MONODROID_TRUE"; then :
default_profile=monodroid
.\" Author:
.\" Miguel de Icaza (miguel@gnu.org)
.\"
-.TH Mono "Mono 4.5.2"
+.TH Mono "Mono 4.7.0"
.SH NAME
mono \- Mono's ECMA-CLI native code generator (Just-in-Time and Ahead-of-Time)
.SH SYNOPSIS
to force all of your Mono processes to use LLVM or SGEN without having
to modify any launch scripts.
.TP
-\fBMONO_ENV_OPTIONS\fR
+\fBMONO_SDB_ENV_OPTIONS\fR
Used to pass extra options to the debugger agent in the runtime, as they were passed
using --debugger-agent=.
.TP
.TP
\fBcollect-before-allocs\fR
.TP
-\fBcheck-at-minor-collections\fR
-This performs a consistency check on minor collections and also clears
-the nursery at collection time, instead of the default, when buffers
-are allocated (clear-at-gc). The consistency check ensures that
-there are no major to minor references that are not on the remembered
-sets.
+\fBcheck-remset-consistency\fR
+This performs a remset consistency check at various opportunities, and
+also clears the nursery at collection time, instead of the default,
+when buffers are allocated (clear-at-gc). The consistency check
+ensures that there are no major to minor references that are not on
+the remembered sets.
.TP
\fBmod-union-consistency-check\fR
Checks that the mod-union cardtable is consistent before each
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System System.Data System.Xml
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
+++ /dev/null
-//
-// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.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;
-using System.Runtime.CompilerServices;
-
-[assembly: AssemblyTitle ("System.IO.Compression.dll")]
-[assembly: AssemblyDescription ("System.IO.Compression.dll")]
-[assembly: AssemblyDefaultAlias ("System.IO.Compression.dll")]
-[assembly: AssemblyCompany ("Xamarin, Inc.")]
-[assembly: AssemblyProduct ("Mono Common Language Infrastructure")]
-[assembly: AssemblyCopyright ("Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)")]
-[assembly: AssemblyVersion ("4.0.0.0")]
-[assembly: AssemblyInformationalVersion ("4.0.0.0")]
-[assembly: AssemblyFileVersion ("4.0.0.0")]
-[assembly: AssemblyDelaySign (true)]
-[assembly: AssemblyKeyFile ("../../msfinal.pub")]
-
-[assembly: ReferenceAssembly]
-
-
+++ /dev/null
-MCS_BUILD_DIR = ../../../build
-
-thisdir = class/Facades/System.IO.Compression
-SUBDIRS =
-include $(MCS_BUILD_DIR)/rules.make
-
-LIBRARY_SUBDIR = Facades
-LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)/Facades
-
-LIBRARY = System.IO.Compression.dll
-
-KEY_FILE = ../../msfinal.pub
-SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699
-LIB_REFS = System
-LIB_MCS_FLAGS = $(SIGN_FLAGS)
-
-PLATFORM_DEBUG_FLAGS =
-
-NO_TEST = yes
-
-include $(MCS_BUILD_DIR)/library.make
-
-
+++ /dev/null
-// This is stub only. The implementation should come from https://github.com/dotnet/corefx/tree/master/src/System.IO.Compression/src/System/IO/Compression
-
-namespace System.IO.Compression
-{
- public class ZipArchive : System.IDisposable
- {
- public ZipArchive(System.IO.Stream stream) { }
- public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode) { }
- public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen) { }
- public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen, System.Text.Encoding entryNameEncoding) { }
- public System.Collections.ObjectModel.ReadOnlyCollection<System.IO.Compression.ZipArchiveEntry> Entries { get { return default(System.Collections.ObjectModel.ReadOnlyCollection<System.IO.Compression.ZipArchiveEntry>); } }
- public System.IO.Compression.ZipArchiveMode Mode { get { return default(System.IO.Compression.ZipArchiveMode); } }
- public System.IO.Compression.ZipArchiveEntry CreateEntry(string entryName) { return default(System.IO.Compression.ZipArchiveEntry); }
- public System.IO.Compression.ZipArchiveEntry CreateEntry(string entryName, System.IO.Compression.CompressionLevel compressionLevel) { return default(System.IO.Compression.ZipArchiveEntry); }
- public void Dispose() { }
- protected virtual void Dispose(bool disposing) { }
- public System.IO.Compression.ZipArchiveEntry GetEntry(string entryName) { return default(System.IO.Compression.ZipArchiveEntry); }
- }
-
- public partial class ZipArchiveEntry
- {
- internal ZipArchiveEntry() { }
- public System.IO.Compression.ZipArchive Archive { get { return default(System.IO.Compression.ZipArchive); } }
- public long CompressedLength { get { return default(long); } }
- public string FullName { get { return default(string); } }
- public System.DateTimeOffset LastWriteTime { get { return default(System.DateTimeOffset); } set { } }
- public long Length { get { return default(long); } }
- public string Name { get { return default(string); } }
- public void Delete() { }
- public System.IO.Stream Open() { return default(System.IO.Stream); }
- public override string ToString() { return default(string); }
- }
-
- public enum ZipArchiveMode
- {
- Create = 1,
- Read = 0,
- Update = 2,
- }
-}
\ No newline at end of file
+++ /dev/null
-TypeForwarders.cs
-AssemblyInfo.cs
-Missing.cs
+++ /dev/null
-//
-// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.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.
-//
-
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.IO.Compression.CompressionLevel))]
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.IO.Compression.CompressionMode))]
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.IO.Compression.DeflateStream))]
-[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.IO.Compression.GZipStream))]
-
-
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System.Runtime.Serialization
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_MCS_FLAGS += /d:NO_CODEDOM
endif
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System System.Core
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System.Core
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
namespace System.Text
{
- public sealed partial class CodePagesEncodingProvider
+ public sealed class CodePagesEncodingProvider : EncodingProvider
{
+ static readonly CodePagesEncodingProvider instance = new CodePagesEncodingProvider ();
+
private CodePagesEncodingProvider ()
{
}
- public static System.Text.EncodingProvider Instance {
+ public static EncodingProvider Instance {
get {
- throw new NotImplementedException ();
+ return instance;
}
}
+
+ public override Encoding GetEncoding (string name)
+ {
+ // MSDN: "if name is not the name of an encoding that you support, the method should return null."
+ // We do this here since all our encodings are already supported by the main Encoding class
+ return null;
+ }
+
+ public override Encoding GetEncoding (int codepage)
+ {
+ // MSDN: "if codepage is not the code page identifier of an encoding that you support, the method should return null."
+ // We do this here since all our encodings are already supported by the main Encoding class
+ return null;
+ }
}
}
\ No newline at end of file
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System
LIB_MCS_FLAGS = $(SIGN_FLAGS) -unsafe
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
LIB_REFS = System System.Xml System.Xml.Linq
LIB_MCS_FLAGS = $(SIGN_FLAGS)
-PLATFORM_DEBUG_FLAGS =
-
NO_TEST = yes
include $(MCS_BUILD_DIR)/library.make
System.Security.Principal.Windows System.Threading.Thread System.Threading.ThreadPool \
System.Xml.XPath System.Xml.XmlDocument System.Xml.Xsl.Primitives Microsoft.Win32.Registry.AccessControl System.Diagnostics.StackTrace System.Globalization.Extensions \
System.IO.FileSystem.AccessControl System.Private.CoreLib.InteropServices System.Reflection.TypeExtensions \
-System.Security.SecureString System.Threading.AccessControl System.Threading.Overlapped System.Xml.XPath.XDocument System.IO.Compression \
+System.Security.SecureString System.Threading.AccessControl System.Threading.Overlapped System.Xml.XPath.XDocument \
System.Security.Cryptography.Algorithms System.Security.Cryptography.Primitives System.Text.Encoding.CodePages System.IO.FileSystem.Watcher \
System.Security.Cryptography.ProtectedData System.ServiceProcess.ServiceController System.IO.Pipes
# The test exe is not profile specific, and compiling a 2.0 will make the 4.5 tests fail
ifdef VALID_TEST_PROFILE
+TEST_HELPERS_SOURCES = \
+ ../test-helpers/NetworkHelpers.cs
+
test-local: dtest-app.exe dtest-excfilter.exe
-dtest-app.exe: Test/dtest-app.cs
- $(CSCOMPILE) -r:$(topdir)/class/lib/$(PROFILE)/System.Core.dll -r:$(topdir)/class/lib/$(PROFILE)/System.dll -out:$@ -unsafe $(PLATFORM_DEBUG_FLAGS) -optimize- Test/dtest-app.cs
+dtest-app.exe: Test/dtest-app.cs $(TEST_HELPERS_SOURCES)
+ $(CSCOMPILE) -r:$(topdir)/class/lib/$(PROFILE)/System.Core.dll -r:$(topdir)/class/lib/$(PROFILE)/System.dll -out:$@ -unsafe $(PLATFORM_DEBUG_FLAGS) -optimize- Test/dtest-app.cs $(TEST_HELPERS_SOURCES)
dtest-excfilter.exe: Test/dtest-excfilter.il
MONO_PATH=$(topdir)/class/lib/$(PROFILE) $(INTERNAL_ILASM) -out:$@ /exe /debug Test/dtest-excfilter.il
using System.Reflection.Emit;
using System.Diagnostics;
using System.Threading;
+using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Sockets;
+using MonoTests.Helpers;
public class TestsBase
{
wait_one ();
return 0;
}
+ if (args.Length >0 && args [0] == "threadpool-io") {
+ threadpool_io ();
+ return 0;
+ }
breakpoints ();
single_stepping ();
arguments ();
public override string virtual_method () {
return "V2";
}
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void threadpool_bp () { }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void threadpool_io () {
+ // Start a threadpool task that blocks on I/O.
+ // Regression test for #42625
+ const int nbytes = 16;
+ var bsOut = new byte[nbytes];
+ for (int i = 0; i < nbytes; i++) {
+ bsOut[i] = (byte)i;
+ }
+ var endPoint = NetworkHelpers.LocalEphemeralEndPoint ();
+ var l = new TcpListener (endPoint);
+ l.Start ();
+ Task<byte[]> t = Task.Run (async () => {
+ var c = new TcpClient ();
+ await c.ConnectAsync (endPoint.Address, endPoint.Port);
+ var streamIn = c.GetStream ();
+ var bs = new byte[nbytes];
+ int nread = 0;
+ int nremain = nbytes;
+ while (nread < nbytes) {
+ int r = await streamIn.ReadAsync (bs, nread, nremain);
+ nread += r;
+ nremain -= r;
+ }
+ streamIn.Close ();
+ return bs;
+ });
+ var s = l.AcceptTcpClient ();
+ l.Stop ();
+ // write bytes in two groups so that the task blocks on the ReadAsync
+ var streamOut = s.GetStream ();
+ var nbytesFirst = nbytes / 2;
+ var nbytesRest = nbytes - nbytesFirst;
+ streamOut.Write (bsOut, 0, nbytesFirst);
+ threadpool_bp ();
+ streamOut.Write (bsOut, nbytesFirst, nbytesRest);
+ streamOut.Close ();
+ var bsIn = t.Result;
+ }
}
class TypeLoadClass {
// Make sure we are still in the cctor
Assert.AreEqual (".cctor", e.Thread.GetFrames ()[0].Location.Method.Name);
}
+
+ [Test]
+ public void ThreadpoolIOsinglestep () {
+ TearDown ();
+ Start ("dtest-app.exe", "threadpool-io");
+ // This is a regression test for #42625. It tests the
+ // interaction (particularly in coop GC) of the
+ // threadpool I/O mechanism and the soft debugger.
+ Event e = run_until ("threadpool_io");
+ // run until we sent the task half the bytes it
+ // expects, so that it blocks waiting for the rest.
+ e = run_until ("threadpool_bp");
+ var req = create_step (e);
+ e = step_out (); // leave threadpool_bp
+ e = step_out (); // leave threadpool_io
+ }
}
}
#include monodroid_Mono.Security_test.dll.build-failure-exclude.sources
-#include monodroid_Mono.Data.Sqlite_test.dll.new-exclude.sources
+#include monodroid_Mono.Security_test.dll.new-exclude.sources
+
namespace MonoTests.System
{
[TestFixture]
- public class ContinuationsTest {
-
- private Continuation _contA = new Continuation();
-
- private int total = 0;
-
- [Test]
- public void TestContinuationsLoop() {
- _contA.Mark();
- int value = 0;
- int ret = _contA.Store(0);
- for(int i = ret; i < 10; i++) {
- value += i;
- }
-
- if(value > 0) {
- total += value;
- _contA.Restore(ret + 1);
- }
-
- Assert.AreEqual(total,330);
- }
-
- private int yields = 0;
-
- [Test]
- public void Yielding() {
- Continuation baseCont = new Continuation();
- Continuation taskCont = new Continuation();
-
- baseCont.Mark();
- taskCont.Mark();
-
- // Store the base continuation to start the task
- if (baseCont.Store(0) == 0) {
- bool done = false;
- int count = 0;
-
- while (!done) {
- // Do stuff for the task.
- ++count;
-
- // This task is counting to 100.
- if (count == 100) {
- done = true;
- }
-
- // Yield every 10 loops
- else if (count % 10 == 0) {
-
- // To yield, store the task continuation then restore
- // the base continuation.
- if (taskCont.Store(0) == 0) {
- baseCont.Restore(1);
- }
- }
- }
- }
- // When restored, 'Store' will return what was passed to Restore, in this case 1 so fall here.
- else {
- // Count the yields, then go back to the task.
- ++yields;
- taskCont.Restore(1);
- }
-
- Assert.AreEqual(9, yields);
- }
-
-
- public class MicroThread {
-
- public void Yield() {
- if (MyThread.Store(0) == 0) {
- MainThread.Restore(1);
- }
- }
-
- public void Resume() {
- if (MainThread.Store(0) == 0) {
- MyThread.Restore(1);
- }
- }
-
- public void DoWork(Action action) {
- if (MainThread.Store(0) == 0) {
- action();
- Done = true;
- MainThread.Restore(1);
- }
- }
-
- public bool Done = false;
- public Continuation MainThread = new Continuation();
- public Continuation MyThread = new Continuation();
- }
-
- public class MicroBJob {
- private int _Count = 0;
- public int Count {
- get { return _Count; }
- set { _Count = value;}
- }
-
- public MicroThread MicroThread;
- public void Work() {
- while (Count < 100) {
- ++Count;
- if (Count % 10 == 0) {
- MicroThread.Yield();
- }
- }
- }
- }
-
- [Test]
- public void MicroThreadTest() {
- MicroThread microA = new MicroThread();
- MicroThread microB = new MicroThread();
-
- microA.MainThread.Mark();
- microA.MyThread.Mark();
- microB.MainThread.Mark();
- microB.MyThread.Mark();
-
- Assert.AreEqual(false,microA.Done);
- Assert.AreEqual(false,microB.Done);
-
- microA.DoWork( () => {
- int count = 0;
- while (count < 100) {
- ++count;
- if (count % 10 == 0) {
- microA.Yield();
- }
- }
- });
-
- MicroBJob jobB = new MicroBJob();
- jobB.MicroThread = microB;
-
- microB.DoWork(jobB.Work);
-
- Assert.AreEqual(false,microA.Done);
- Assert.AreEqual(false,microB.Done);
-
- int yields = 0;
- while (yields < 20) {
- if (!microA.Done) microA.Resume();
- if (!microB.Done) microB.Resume();
- if (microA.Done && microB.Done) break;
- ++yields;
- }
-
- Assert.AreEqual(true,microA.Done);
- Assert.AreEqual(true,microB.Done);
- Assert.AreEqual(100,jobB.Count);
- Assert.AreEqual(9,yields);
- }
- }
+ public class ContinuationsTest
+ {
+ [TestFixtureSetUp]
+ public void FixtureSetUp ()
+ {
+ try {
+ var temp = new Continuation ();
+ } catch (NotImplementedException) {
+ Assert.Ignore ("This platform doesn't support Tasklets.");
+ }
+ }
+
+ int total = 0;
+
+ [Test]
+ public void TestContinuationsLoop()
+ {
+ Continuation _contA = new Continuation();
+
+ _contA.Mark();
+ int value = 0;
+ int ret = _contA.Store(0);
+ for (int i = ret; i < 10; i++) {
+ value += i;
+ }
+
+ if (value > 0) {
+ total += value;
+ _contA.Restore(ret + 1);
+ }
+
+ Assert.AreEqual(total, 330);
+ }
+
+ private int yields = 0;
+
+ [Test]
+ public void Yielding()
+ {
+ Continuation baseCont = new Continuation();
+ Continuation taskCont = new Continuation();
+
+ baseCont.Mark();
+ taskCont.Mark();
+
+ // Store the base continuation to start the task
+ if (baseCont.Store(0) == 0) {
+ bool done = false;
+ int count = 0;
+
+ while (!done) {
+ // Do stuff for the task.
+ ++count;
+
+ // This task is counting to 100.
+ if (count == 100) {
+ done = true;
+ }
+
+ // Yield every 10 loops
+ else if (count % 10 == 0) {
+
+ // To yield, store the task continuation then restore
+ // the base continuation.
+ if (taskCont.Store(0) == 0) {
+ baseCont.Restore(1);
+ }
+ }
+ }
+ }
+ // When restored, 'Store' will return what was passed to Restore, in this case 1 so fall here.
+ else {
+ // Count the yields, then go back to the task.
+ ++yields;
+ taskCont.Restore(1);
+ }
+
+ Assert.AreEqual(9, yields);
+ }
+
+
+ public class MicroThread
+ {
+
+ public void Yield()
+ {
+ if (MyThread.Store(0) == 0) {
+ MainThread.Restore(1);
+ }
+ }
+
+ public void Resume()
+ {
+ if (MainThread.Store(0) == 0) {
+ MyThread.Restore(1);
+ }
+ }
+
+ public void DoWork(Action action)
+ {
+ if (MainThread.Store(0) == 0) {
+ action();
+ Done = true;
+ MainThread.Restore(1);
+ }
+ }
+
+ public bool Done = false;
+ public Continuation MainThread = new Continuation();
+ public Continuation MyThread = new Continuation();
+ }
+
+ public class MicroBJob
+ {
+ private int _Count = 0;
+ public int Count
+ {
+ get { return _Count; }
+ set { _Count = value; }
+ }
+
+ public MicroThread MicroThread;
+ public void Work()
+ {
+ while (Count < 100) {
+ ++Count;
+ if (Count % 10 == 0) {
+ MicroThread.Yield();
+ }
+ }
+ }
+ }
+
+ [Test]
+ public void MicroThreadTest()
+ {
+ MicroThread microA = new MicroThread();
+ MicroThread microB = new MicroThread();
+
+ microA.MainThread.Mark();
+ microA.MyThread.Mark();
+ microB.MainThread.Mark();
+ microB.MyThread.Mark();
+
+ Assert.AreEqual(false, microA.Done);
+ Assert.AreEqual(false, microB.Done);
+
+ microA.DoWork(() =>
+ {
+ int count = 0;
+ while (count < 100) {
+ ++count;
+ if (count % 10 == 0) {
+ microA.Yield();
+ }
+ }
+ });
+
+ MicroBJob jobB = new MicroBJob();
+ jobB.MicroThread = microB;
+
+ microB.DoWork(jobB.Work);
+
+ Assert.AreEqual(false, microA.Done);
+ Assert.AreEqual(false, microB.Done);
+
+ int yields = 0;
+ while (yields < 20) {
+ if (!microA.Done) microA.Resume();
+ if (!microB.Done) microB.Resume();
+ if (microA.Done && microB.Done) break;
+ ++yields;
+ }
+
+ Assert.AreEqual(true, microA.Done);
+ Assert.AreEqual(true, microB.Done);
+ Assert.AreEqual(100, jobB.Count);
+ Assert.AreEqual(9, yields);
+ }
+ }
}
-
-// vim: noexpandtab
-// Local Variables:
-// tab-width: 4
-// c-basic-offset: 4
-// indent-tabs-mode: t
-// End:
../../build/common/SR.cs
+../../build/common/MonoTODOAttribute.cs
Assembly/AssemblyInfo.cs
System/Util.cs
namespace Microsoft.SqlServer.Server
{
- public sealed class SqlDataRecord : IDataRecord
+ public class SqlDataRecord : IDataRecord
{
- public bool GetBoolean (int ordinal)
+ public SqlDataRecord (params SqlMetaData[] metaData)
+ {
+ }
+
+ public virtual bool GetBoolean (int ordinal)
{
throw new NotImplementedException ();
}
- public byte GetByte (int ordinal)
+ public virtual byte GetByte (int ordinal)
{
throw new NotImplementedException ();
}
- public long GetBytes (int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length)
+ public virtual long GetBytes (int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length)
{
throw new NotImplementedException ();
}
- public char GetChar (int ordinal)
+ public virtual char GetChar (int ordinal)
{
throw new NotImplementedException ();
}
- public long GetChars (int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length)
+ public virtual long GetChars (int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length)
{
throw new NotImplementedException ();
}
- public IDataReader GetData (int ordinal)
+ public virtual IDataReader GetData (int ordinal)
{
throw new NotImplementedException ();
}
- public string GetDataTypeName (int ordinal)
+ public virtual string GetDataTypeName (int ordinal)
{
throw new NotImplementedException ();
}
- public DateTime GetDateTime (int ordinal)
+ public virtual DateTime GetDateTime (int ordinal)
{
throw new NotImplementedException ();
}
- public decimal GetDecimal (int ordinal)
+ public virtual decimal GetDecimal (int ordinal)
{
throw new NotImplementedException ();
}
- public double GetDouble (int ordinal)
+ public virtual double GetDouble (int ordinal)
{
throw new NotImplementedException ();
}
- public System.Type GetFieldType (int ordinal)
+ public virtual System.Type GetFieldType (int ordinal)
{
throw new NotImplementedException ();
}
- public float GetFloat (int ordinal)
+ public virtual float GetFloat (int ordinal)
{
throw new NotImplementedException ();
}
- public Guid GetGuid (int ordinal)
+ public virtual Guid GetGuid (int ordinal)
{
throw new NotImplementedException ();
}
- public short GetInt16 (int ordinal)
+ public virtual short GetInt16 (int ordinal)
{
throw new NotImplementedException ();
}
- public int GetInt32 (int ordinal)
+ public virtual int GetInt32 (int ordinal)
{
throw new NotImplementedException ();
}
- public long GetInt64 (int ordinal)
+ public virtual long GetInt64 (int ordinal)
{
throw new NotImplementedException ();
}
- public string GetName (int ordinal)
+ public virtual string GetName (int ordinal)
{
throw new NotImplementedException ();
}
- public int GetOrdinal (string name)
+ public virtual int GetOrdinal (string name)
{
throw new NotImplementedException ();
}
- public string GetString (int ordinal)
+ public virtual string GetString (int ordinal)
{
throw new NotImplementedException ();
}
- public object GetValue (int ordinal)
+ public virtual object GetValue (int ordinal)
{
throw new NotImplementedException ();
}
- public int GetValues (object[] values)
+ public virtual int GetValues (object[] values)
{
throw new NotImplementedException ();
}
- public bool IsDBNull (int ordinal)
+ public virtual bool IsDBNull (int ordinal)
{
throw new NotImplementedException ();
}
- public int FieldCount {
+ public virtual int FieldCount {
get {
throw new NotImplementedException ();
}
}
- public object this [string name] {
+ public virtual object this [string name] {
get {
throw new NotImplementedException ();
}
}
- public object this [int ordinal] {
+ public virtual object this [int ordinal] {
get {
throw new NotImplementedException ();
}
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Proxy_Disabled ()
{
var pp = WebRequest.DefaultWebProxy;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_Default ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_Version_1_0 ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_ClientHandlerSettings ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_CustomHeaders ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_CustomHeaders_SpecialSeparators ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_CustomHeaders_Host ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Transfer_Encoding_Chunked ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Transfer_Encoding_Custom ()
{
bool? failed = null;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_Content ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_Content_MaxResponseContentBufferSize ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_Content_MaxResponseContentBufferSize_Error ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_NoContent ()
{
foreach (var method in new HttpMethod[] { HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete }) {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Complete_Error ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Content_Get ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Content_BomEncoding ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Content_Put ()
{
bool passed = false;
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Send_Content_Put_CustomStream ()
{
bool passed = false;
[Test]
[Category ("MobileNotWorking")] // Missing encoding
+ [Category ("RequiresBSDSockets")]
public void GetString_Many ()
{
Action<HttpListenerContext> context = (HttpListenerContext l) => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void GetByteArray_ServerError ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void DisallowAutoRedirect ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void RequestUriAfterRedirect ()
{
var listener = CreateListener (l => {
}
[Test]
+ [Category ("RequiresBSDSockets")]
/*
* Properties may only be modified before sending the first request.
*/
bool result;
#if MONODROID
- result = AndroidPlatform.TrustEvaluateSsl (certs);
- if (result) {
- // chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on
- // Android (there are no mozroots or preinstalled root certificates),
- // thus `errors` will ALWAYS have RemoteCertificateChainErrors.
- // Android just verified the chain; clear RemoteCertificateChainErrors.
- errors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
+ try {
+ result = AndroidPlatform.TrustEvaluateSsl (certs);
+ if (result) {
+ // FIXME: check whether this is still correct.
+ //
+ // chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on
+ // Android (there are no mozroots or preinstalled root certificates),
+ // thus `errors` will ALWAYS have RemoteCertificateChainErrors.
+ // Android just verified the chain; clear RemoteCertificateChainErrors.
+ errors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
+ } else {
+ errors |= SslPolicyErrors.RemoteCertificateChainErrors;
+ status11 = unchecked((int)0x800B010B);
+ }
+ } catch {
+ result = false;
+ errors |= SslPolicyErrors.RemoteCertificateChainErrors;
+ status11 = unchecked((int)0x800B010B);
+ // Ignore
}
#else
if (is_macosx) {
InnerList.AddRange (processModules);
}
-#if !NET_2_1
public ProcessModule this[int index] {
get {
return (ProcessModule)InnerList[index];
{
return InnerList.IndexOf (module);
}
-#endif
}
}
InnerList.AddRange (processThreads);
}
-#if !NET_2_1
public ProcessThread this[int index] {
get {
return (ProcessThread)InnerList[index];
{
InnerList.Remove (thread);
}
-#endif
}
}
namespace MonoTests.System.Net.Mail
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class SmtpClientTest
{
SmtpClient smtp;
{
[TestFixture]
+[Category ("RequiresBSDSockets")]
public class SslStreamTest {
byte[] m_serverCertRaw = { 48, 130, 5, 165, 2, 1, 3, 48, 130, 5, 95, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 5, 80, 4, 130, 5, 76, 48, 130, 5, 72, 48, 130, 2, 87, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 6, 160, 130, 2, 72, 48, 130, 2, 68, 2, 1, 0, 48, 130, 2, 61, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 211, 176, 234, 3, 252, 26, 32, 15, 2, 2, 7, 208, 128, 130, 2, 16, 183, 149, 35, 180, 127, 95, 163, 122, 138, 244, 29, 177, 220, 173, 46, 73, 208, 217, 211, 190, 164, 183, 21, 110, 33, 122, 98, 163, 251, 16, 23, 106, 154, 14, 52, 177, 3, 12, 248, 226, 48, 123, 211, 6, 216, 6, 192, 175, 203, 142, 141, 143, 252, 178, 7, 162, 81, 232, 159, 42, 56, 177, 191, 53, 7, 146, 189, 236, 75, 140, 210, 143, 11, 103, 64, 58, 10, 73, 123, 39, 97, 119, 166, 114, 123, 65, 68, 214, 42, 17, 156, 122, 8, 58, 184, 134, 255, 48, 64, 20, 229, 247, 196, 12, 130, 56, 176, 69, 179, 254, 216, 45, 25, 244, 240, 116, 88, 137, 66, 13, 18, 202, 199, 59, 200, 245, 19, 175, 232, 217, 211, 12, 191, 222, 26, 162, 253, 73, 201, 48, 61, 3, 248, 117, 16, 71, 233, 183, 90, 110, 91, 116, 56, 133, 223, 148, 19, 78, 140, 123, 159, 203, 78, 15, 172, 39, 190, 39, 71, 180, 155, 48, 156, 116, 212, 52, 1, 231, 201, 196, 73, 87, 68, 104, 208, 40, 104, 32, 218, 235, 245, 84, 136, 168, 51, 9, 93, 126, 46, 80, 180, 240, 144, 79, 88, 87, 159, 24, 108, 186, 9, 20, 48, 100, 148, 250, 4, 163, 115, 131, 44, 13, 38, 222, 117, 196, 196, 128, 114, 149, 97, 93, 37, 191, 3, 192, 231, 88, 80, 218, 147, 8, 192, 165, 27, 206, 56, 42, 157, 230, 223, 130, 253, 169, 182, 245, 192, 181, 18, 212, 133, 168, 73, 92, 66, 197, 117, 245, 107, 127, 23, 146, 249, 41, 66, 219, 210, 207, 221, 205, 205, 15, 110, 92, 12, 207, 76, 239, 4, 13, 129, 127, 170, 205, 253, 148, 208, 24, 129, 24, 210, 220, 85, 45, 179, 137, 66, 134, 142, 22, 112, 48, 160, 236, 232, 38, 83, 101, 55, 51, 18, 110, 99, 69, 41, 173, 107, 233, 11, 199, 23, 61, 135, 222, 94, 74, 29, 219, 80, 128, 167, 186, 254, 235, 42, 96, 134, 5, 13, 90, 59, 231, 137, 195, 207, 28, 165, 12, 218, 5, 72, 102, 61, 135, 198, 73, 250, 97, 89, 214, 179, 244, 194, 23, 142, 157, 4, 243, 90, 69, 54, 10, 139, 76, 95, 40, 225, 219, 59, 15, 54, 182, 206, 142, 228, 248, 79, 156, 129, 246, 63, 6, 6, 236, 44, 67, 116, 213, 170, 47, 193, 186, 139, 25, 80, 166, 57, 99, 231, 156, 191, 117, 65, 76, 7, 243, 244, 127, 225, 210, 190, 164, 141, 46, 36, 99, 111, 203, 133, 127, 80, 28, 61, 160, 36, 132, 182, 16, 41, 39, 185, 232, 123, 32, 57, 189, 100, 152, 38, 205, 5, 189, 240, 65, 3, 191, 73, 85, 12, 209, 180, 1, 194, 70, 124, 57, 71, 48, 230, 235, 122, 175, 157, 35, 233, 83, 40, 20, 169, 224, 14, 11, 216, 48, 194, 105, 25, 187, 210, 182, 6, 184, 73, 95, 85, 210, 227, 113, 58, 10, 186, 175, 254, 25, 102, 39, 3, 2, 200, 194, 197, 200, 224, 77, 164, 8, 36, 114, 48, 130, 2, 233, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 2, 218, 4, 130, 2, 214, 48, 130, 2, 210, 48, 130, 2, 206, 6, 11, 42, 134, 72, 134, 247, 13, 1, 12, 10, 1, 2, 160, 130, 2, 166, 48, 130, 2, 162, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 178, 13, 52, 135, 85, 49, 79, 105, 2, 2, 7, 208, 4, 130, 2, 128, 21, 84, 227, 109, 230, 144, 140, 170, 117, 250, 179, 207, 129, 100, 126, 126, 29, 231, 94, 140, 45, 26, 168, 45, 240, 4, 170, 73, 98, 115, 109, 96, 177, 206, 6, 80, 170, 22, 237, 144, 58, 95, 59, 26, 85, 135, 178, 69, 184, 44, 122, 81, 213, 135, 149, 198, 246, 83, 68, 129, 2, 186, 118, 33, 44, 214, 227, 240, 220, 51, 175, 220, 220, 180, 113, 216, 101, 138, 81, 54, 38, 0, 216, 30, 29, 187, 213, 230, 12, 181, 130, 21, 241, 98, 120, 41, 150, 176, 69, 37, 169, 249, 123, 212, 254, 135, 154, 214, 127, 39, 105, 149, 180, 218, 41, 207, 75, 70, 105, 169, 185, 169, 132, 173, 188, 82, 251, 71, 234, 136, 5, 254, 110, 223, 34, 4, 145, 7, 19, 51, 123, 140, 75, 226, 0, 21, 220, 228, 223, 218, 8, 169, 210, 194, 139, 93, 218, 55, 40, 174, 50, 238, 38, 166, 222, 103, 0, 209, 88, 131, 51, 222, 154, 217, 18, 172, 73, 17, 133, 54, 173, 208, 118, 104, 167, 113, 153, 223, 251, 154, 120, 176, 18, 127, 51, 206, 164, 77, 86, 9, 82, 212, 86, 162, 206, 230, 79, 217, 178, 42, 217, 162, 152, 188, 217, 59, 212, 117, 200, 135, 75, 74, 43, 1, 42, 79, 180, 164, 250, 122, 103, 103, 157, 11, 14, 33, 48, 8, 108, 155, 46, 124, 223, 204, 169, 124, 104, 11, 246, 213, 226, 16, 125, 17, 228, 15, 178, 141, 79, 78, 115, 76, 131, 122, 166, 124, 154, 1, 174, 178, 176, 213, 208, 188, 71, 118, 220, 168, 64, 218, 176, 134, 38, 229, 14, 109, 162, 125, 16, 57, 249, 201, 180, 17, 182, 143, 184, 12, 248, 113, 65, 70, 109, 79, 249, 34, 170, 35, 228, 219, 121, 202, 228, 121, 127, 255, 22, 173, 202, 171, 33, 232, 4, 240, 142, 216, 80, 56, 177, 83, 93, 123, 217, 213, 157, 99, 34, 194, 61, 228, 239, 194, 20, 27, 9, 53, 132, 79, 19, 97, 107, 31, 51, 39, 176, 223, 90, 88, 67, 138, 194, 169, 176, 144, 202, 119, 146, 74, 27, 118, 63, 129, 230, 101, 104, 75, 116, 49, 223, 254, 225, 70, 206, 183, 11, 134, 148, 10, 55, 57, 50, 178, 144, 164, 139, 233, 169, 109, 186, 211, 95, 123, 75, 111, 192, 187, 127, 240, 45, 226, 194, 240, 128, 10, 79, 178, 192, 66, 21, 197, 24, 171, 141, 255, 185, 230, 84, 206, 151, 9, 93, 115, 162, 12, 115, 129, 218, 103, 219, 183, 142, 123, 3, 110, 139, 208, 4, 146, 76, 99, 246, 240, 32, 169, 148, 16, 146, 172, 230, 36, 56, 145, 23, 94, 209, 92, 38, 244, 127, 70, 121, 253, 66, 55, 36, 140, 98, 105, 233, 112, 24, 23, 230, 112, 62, 244, 12, 48, 30, 51, 0, 18, 244, 139, 66, 245, 234, 203, 195, 52, 119, 255, 84, 82, 204, 100, 176, 167, 24, 224, 8, 127, 214, 148, 115, 242, 56, 190, 72, 221, 68, 252, 36, 74, 254, 57, 52, 96, 20, 173, 32, 236, 87, 15, 16, 76, 9, 48, 3, 61, 2, 137, 137, 9, 68, 213, 99, 163, 63, 201, 83, 241, 98, 7, 117, 108, 4, 123, 170, 18, 10, 19, 198, 31, 170, 15, 247, 216, 145, 172, 239, 137, 181, 80, 160, 24, 11, 35, 131, 58, 218, 22, 250, 215, 52, 160, 246, 197, 183, 92, 137, 0, 245, 63, 49, 183, 246, 195, 58, 63, 4, 75, 10, 92, 131, 181, 59, 78, 247, 44, 150, 49, 49, 107, 211, 62, 71, 62, 222, 159, 161, 118, 236, 55, 219, 49, 0, 3, 82, 236, 96, 20, 83, 39, 245, 208, 240, 245, 174, 218, 49, 21, 48, 19, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 21, 49, 6, 4, 4, 1, 0, 0, 0, 48, 61, 48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20, 30, 154, 48, 126, 198, 239, 114, 62, 12, 58, 129, 172, 67, 156, 76, 214, 62, 205, 89, 28, 4, 20, 135, 177, 105, 83, 79, 93, 181, 149, 169, 49, 112, 201, 70, 212, 153, 79, 198, 163, 137, 90, 2, 2, 7, 208 };
namespace MonoTests.System.Net.Sockets
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class NetworkStreamTest
{
[Test]
namespace MonoTests.System.Net.Sockets
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class SocketAcceptAsyncTest
{
[Test]
namespace MonoTests.System.Net.Sockets
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class SocketAsyncTest
{
Socket serverSocket;
namespace MonoTests.System.Net.Sockets
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class SocketTest
{
// note: also used in SocketCas tests
/// Tests System.Net.Sockets.TcpClient
/// </summary>
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class TcpClientTest
{
namespace MonoTests.System.Net.Sockets
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class TcpListenerTest
{
[Test]
namespace MonoTests.System.Net.Sockets {
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class UdpClientTest {
[Test] // .ctor ()
public void Constructor1 ()
namespace MonoTests.System.Net
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class CookieParserTest
{
public const string A = "Foo=Bar, expires=World; expires=Sat, 11-Oct-14 22:45:19 GMT, A=B";
namespace MonoTests.System.Net\r
{\r
[TestFixture]\r
+ [Category ("RequiresBSDSockets")]\r
public class DnsTest\r
{\r
private String site1Name = "google-public-dns-a.google.com",\r
\r
IAsyncResult async = Dns.BeginResolve (site1Dot, null, null);\r
IPHostEntry entry = Dns.EndResolve (async);\r
- SubTestValidIPHostEntry (entry);
+ SubTestValidIPHostEntry (entry);\r
var ip = GetIPv4Address (entry);\r
Assert.AreEqual (site1Dot, ip.ToString ());\r
}\r
{\r
IPAddress addr = new IPAddress (IPAddress.NetworkToHostOrder ((int) site2IP));\r
IPHostEntry h = Dns.GetHostByAddress (addr);\r
- SubTestValidIPHostEntry (h);
+ SubTestValidIPHostEntry (h);\r
var ip = GetIPv4Address (h);\r
Assert.AreEqual (addr.ToString (), ip.ToString ());\r
}\r
namespace MonoTests.System.Net
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class FileWebRequestTest
{
private string _tempDirectory;
namespace MonoTests.System.Net
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class FtpWebRequestTest
{
FtpWebRequest defaultRequest;
namespace MonoTests.System.Net {
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpListener2Test {
private HttpListener _listener = null;
}
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpListenerBugs {
[Test]
public void TestNonChunkedAsync ()
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void AddOne ()
{
HttpListener listener = new HttpListener ();
}
[Test]
+ [Category ("RequiresBSDSockets")]
public void Duplicate ()
{
HttpListener listener = new HttpListener ();
namespace MonoTests.System.Net
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpListenerRequestTest
{
[Test]
namespace MonoTests.System.Net {
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpListenerTest {
int port;
namespace MonoTests.System.Net
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpWebRequestTest
{
private Random rand = new Random ();
}
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpRequestStreamTest
{
[Test]
namespace MonoTests.System.Net
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpWebResponseTest
{
[Test]
}
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class HttpResponseStreamTest
{
[Test]
namespace MonoTests.System.Net
{
[TestFixture]
+ [Category ("RequiresBSDSockets")]
public class WebClientTest
{
private string _tempFolder;
}\r
[Test] // Covers #41477
+ [Category ("RequiresBSDSockets")]
public void TestReceiveCancelation ()
{
var uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
}
[MethodImpl(MethodImplOptions.InternalCall)]
- unsafe extern static void GPtrArrayFree (RuntimeStructs.GPtrArray* value, bool freeSeg);
+ unsafe extern static void GPtrArrayFree (RuntimeStructs.GPtrArray* value);
- internal static void DestroyAndFree (ref RuntimeGPtrArrayHandle h, bool freeSeg) {
+ internal static void DestroyAndFree (ref RuntimeGPtrArrayHandle h) {
unsafe {
- GPtrArrayFree (h.value, freeSeg);
+ GPtrArrayFree (h.value);
h.value = null;
}
}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono {
+ internal static class RuntimeMarshal {
+ internal static string PtrToUtf8String (IntPtr ptr)
+ {
+ unsafe {
+ return new String ((sbyte*)ptr);
+ }
+ }
+
+ internal static SafeStringMarshal MarshalString (string str)
+ {
+ return new SafeStringMarshal (str);
+ }
+
+ static int DecodeBlobSize (IntPtr in_ptr, out IntPtr out_ptr)
+ {
+ uint size;
+ unsafe {
+ byte *ptr = (byte*)in_ptr;
+
+ if ((*ptr & 0x80) == 0) {
+ size = (uint)(ptr [0] & 0x7f);
+ ptr++;
+ } else if ((*ptr & 0x40) == 0){
+ size = (uint)(((ptr [0] & 0x3f) << 8) + ptr [1]);
+ ptr += 2;
+ } else {
+ size = (uint)(((ptr [0] & 0x1f) << 24) +
+ (ptr [1] << 16) +
+ (ptr [2] << 8) +
+ ptr [3]);
+ ptr += 4;
+ }
+ out_ptr = (IntPtr)ptr;
+ }
+
+ return (int)size;
+ }
+
+ internal static byte[] DecodeBlobArray (IntPtr ptr)
+ {
+ IntPtr out_ptr;
+ int size = DecodeBlobSize (ptr, out out_ptr);
+ byte[] res = new byte [size];
+ Marshal.Copy (out_ptr, res, 0, size);
+ return res;
+ }
+
+ internal static int AsciHexDigitValue (int c)
+ {
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return c - 'A' + 10;
+ }
+
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ internal static extern void FreeAssemblyName (ref MonoAssemblyName name);
+ }
+}
}
}
+ //Maps to metadata-internals.h:: MonoAssemblyName
+ internal unsafe struct MonoAssemblyName
+ {
+ const int MONO_PUBLIC_KEY_TOKEN_LENGTH = 17;
+
+ internal IntPtr name;
+ internal IntPtr culture;
+ internal IntPtr hash_value;
+ internal IntPtr public_key;
+ internal fixed byte public_key_token [MONO_PUBLIC_KEY_TOKEN_LENGTH];
+ internal uint hash_alg;
+ internal uint hash_len;
+ internal uint flags;
+ internal ushort major, minor, build, revision;
+ internal ushort arch;
+ }
}
-
using System.Runtime.CompilerServices;
namespace Mono {
- internal sealed class SafeGPtrArrayHandle : IDisposable {
+ internal struct SafeGPtrArrayHandle : IDisposable {
RuntimeGPtrArrayHandle handle;
- bool freeSeg;
- internal SafeGPtrArrayHandle (IntPtr ptr, bool freeSeg)
+ internal SafeGPtrArrayHandle (IntPtr ptr)
{
handle = new RuntimeGPtrArrayHandle (ptr);
- this.freeSeg = freeSeg;
- }
-
- ~SafeGPtrArrayHandle ()
- {
- Dispose (false);
- }
-
- void Dispose (bool disposing)
- {
- RuntimeGPtrArrayHandle.DestroyAndFree (ref handle, freeSeg);
}
public void Dispose () {
- Dispose (true);
- GC.SuppressFinalize (this);
+ RuntimeGPtrArrayHandle.DestroyAndFree (ref handle);
}
internal int Length {
--- /dev/null
+//
+// Safe wrapper for a string and its UTF8 encoding
+//
+// Authors:
+// Aleksey Kliger <aleksey@xamarin.com>
+// Rodrigo Kumpera <kumpera@xamarin.com>
+//
+// Copyright 2016 Dot net foundation.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Mono {
+ internal struct SafeStringMarshal : IDisposable {
+ readonly string str;
+ IntPtr marshaled_string;
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern static IntPtr StringToUtf8 (string str);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern static void GFree (IntPtr ptr);
+
+ public SafeStringMarshal (string str) {
+ this.str = str;
+ this.marshaled_string = IntPtr.Zero;
+ }
+
+ public IntPtr Value {
+ get {
+ if (marshaled_string == IntPtr.Zero && str != null)
+ marshaled_string = StringToUtf8 (str);
+ return marshaled_string;
+ }
+ }
+
+ public void Dispose () {
+ if (marshaled_string != IntPtr.Zero) {
+ GFree (marshaled_string);
+ marshaled_string = IntPtr.Zero;
+ }
+ }
+ }
+}
static extern Type MakeGenericType (Type gt, Type [] types);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern IntPtr GetMethodsByName_native (string name, BindingFlags bindingAttr, bool ignoreCase);
+ internal extern IntPtr GetMethodsByName_native (IntPtr namePtr, BindingFlags bindingAttr, bool ignoreCase);
internal RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, RuntimeType reflectedType)
{
var refh = new RuntimeTypeHandle (reflectedType);
- using (var h = new Mono.SafeGPtrArrayHandle (GetMethodsByName_native (name, bindingAttr, ignoreCase), false)) {
+ using (var namePtr = new Mono.SafeStringMarshal (name))
+ using (var h = new Mono.SafeGPtrArrayHandle (GetMethodsByName_native (namePtr.Value, bindingAttr, ignoreCase))) {
var n = h.Length;
var a = new RuntimeMethodInfo [n];
for (int i = 0; i < n; i++) {
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern IntPtr GetPropertiesByName_native (string name, BindingFlags bindingAttr, bool icase);
+ extern IntPtr GetPropertiesByName_native (IntPtr name, BindingFlags bindingAttr, bool icase);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern IntPtr GetConstructors_native (BindingFlags bindingAttr);
RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, RuntimeType reflectedType)
{
var refh = new RuntimeTypeHandle (reflectedType);
- using (var h = new Mono.SafeGPtrArrayHandle (GetConstructors_native (bindingAttr), false)) {
+ using (var h = new Mono.SafeGPtrArrayHandle (GetConstructors_native (bindingAttr))) {
var n = h.Length;
var a = new RuntimeConstructorInfo [n];
for (int i = 0; i < n; i++) {
RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, RuntimeType reflectedType)
{
var refh = new RuntimeTypeHandle (reflectedType);
- using (var h = new Mono.SafeGPtrArrayHandle (GetPropertiesByName_native (name, bindingAttr, icase), false)) {
+ using (var namePtr = new Mono.SafeStringMarshal (name))
+ using (var h = new Mono.SafeGPtrArrayHandle (GetPropertiesByName_native (namePtr.Value, bindingAttr, icase))) {
var n = h.Length;
var a = new RuntimePropertyInfo [n];
for (int i = 0; i < n; i++) {
extern int GetGenericParameterPosition ();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern IntPtr GetEvents_native (string name, BindingFlags bindingAttr);
+ extern IntPtr GetEvents_native (IntPtr name, BindingFlags bindingAttr);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern IntPtr GetFields_native (string name, BindingFlags bindingAttr);
+ extern IntPtr GetFields_native (IntPtr name, BindingFlags bindingAttr);
RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, RuntimeType reflectedType)
{
var refh = new RuntimeTypeHandle (reflectedType);
- using (var h = new Mono.SafeGPtrArrayHandle (GetFields_native (name, bindingAttr), false)) {
+ using (var namePtr = new Mono.SafeStringMarshal (name))
+ using (var h = new Mono.SafeGPtrArrayHandle (GetFields_native (namePtr.Value, bindingAttr))) {
int n = h.Length;
var a = new RuntimeFieldInfo[n];
for (int i = 0; i < n; i++) {
RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, RuntimeType reflectedType)
{
var refh = new RuntimeTypeHandle (reflectedType);
- using (var h = new Mono.SafeGPtrArrayHandle (GetEvents_native (name, bindingAttr), false)) {
+ using (var namePtr = new Mono.SafeStringMarshal (name))
+ using (var h = new Mono.SafeGPtrArrayHandle (GetEvents_native (namePtr.Value, bindingAttr))) {
int n = h.Length;
var a = new RuntimeEventInfo[n];
for (int i = 0; i < n; i++) {
public extern override Type[] GetInterfaces();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);
+ extern IntPtr GetNestedTypes_native (IntPtr name, BindingFlags bindingAttr);
+
+ RuntimeType[] GetNestedTypes_internal (string displayName, BindingFlags bindingAttr)
+ {
+ string internalName = null;
+ if (displayName != null)
+ internalName = TypeIdentifiers.FromDisplay (displayName).InternalName;
+ using (var namePtr = new Mono.SafeStringMarshal (internalName))
+ using (var h = new Mono.SafeGPtrArrayHandle (GetNestedTypes_native (namePtr.Value, bindingAttr))) {
+ int n = h.Length;
+ var a = new RuntimeType [n];
+ for (int i = 0; i < n; i++) {
+ var th = new RuntimeTypeHandle (h[i]);
+ a[i] = (RuntimeType) Type.GetTypeFromHandle (th);
+ }
+ return a;
+ }
+ }
public override string AssemblyQualifiedName {
get {
FileShare.None, bufferSize);
}
-#if !NET_2_1
[MonoLimitation ("FileOptions are ignored")]
public static FileStream Create (string path, int bufferSize,
FileOptions options)
{
- return Create (path, bufferSize, options, null);
+ return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
+ FileShare.None, bufferSize, options);
}
-
+
+#if !NET_2_1
[MonoLimitation ("FileOptions and FileSecurity are ignored")]
public static FileStream Create (string path, int bufferSize,
FileOptions options,
public override AssemblyName GetName (bool copiedName)
{
- AssemblyName aname = new AssemblyName ();
- FillName (this, aname);
+ var aname = AssemblyName.Create (this, false);
if (sn != null) {
aname.SetPublicKey (sn.PublicKey);
// Note: changes to fields must be reflected in _MonoReflectionAssembly struct (object-internals.h)
#pragma warning disable 649
- private IntPtr _mono_assembly;
+ internal IntPtr _mono_assembly;
#pragma warning restore 649
private ResolveEventHolder resolve_event_holder;
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname);
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- static extern internal void FillName (Assembly ass, AssemblyName aname);
-
public virtual AssemblyName GetName (Boolean copiedName)
{
throw new NotImplementedException ();
using System.Runtime.CompilerServices;
using System.IO;
+using Mono;
using Mono.Security;
using Mono.Security.Cryptography;
}
[MethodImpl (MethodImplOptions.InternalCall)]
- static extern bool ParseName (AssemblyName aname, string assemblyName);
-
+ static extern bool ParseAssemblyName (IntPtr name, out MonoAssemblyName aname, out bool is_version_definited, out bool is_token_defined);
+
public AssemblyName (string assemblyName)
{
if (assemblyName == null)
throw new ArgumentNullException ("assemblyName");
if (assemblyName.Length < 1)
throw new ArgumentException ("assemblyName cannot have zero length.");
-
- if (!ParseName (this, assemblyName))
- throw new FileLoadException ("The assembly name is invalid.");
+
+ using (var name = RuntimeMarshal.MarshalString (assemblyName)) {
+ MonoAssemblyName nativeName;
+ bool isVersionDefined, isTokenDefined;
+ //ParseName free the name if it fails.
+ if (!ParseAssemblyName (name.Value, out nativeName, out isVersionDefined, out isTokenDefined))
+ throw new FileLoadException ("The assembly name is invalid.");
+ try {
+ unsafe {
+ this.FillName (&nativeName, null, isVersionDefined, false, isTokenDefined);
+ }
+ } finally {
+ RuntimeMarshal.FreeAssemblyName (ref nativeName);
+ }
+ }
}
[MonoLimitation ("Not used, as the values are too limited; Mono supports more")]
contentType = value;
}
}
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ static extern unsafe MonoAssemblyName* GetNativeName (IntPtr assembly_ptr);
+
+ internal unsafe void FillName (MonoAssemblyName *native, string codeBase, bool addVersion, bool addPublickey, bool defaultToken)
+ {
+ this.name = RuntimeMarshal.PtrToUtf8String (native->name);
+
+ this.major = native->major;
+ this.minor = native->minor;
+ this.build = native->build;
+ this.revision = native->revision;
+
+ this.flags = (AssemblyNameFlags)native->flags;
+
+ this.hashalg = (AssemblyHashAlgorithm)native->hash_alg;
+
+ this.versioncompat = AssemblyVersionCompatibility.SameMachine;
+ this.processor_architecture = (ProcessorArchitecture)native->arch;
+
+ if (addVersion)
+ this.version = new Version (this.major, this.minor, this.build, this.revision);
+
+ this.codebase = codeBase;
+
+ if (native->culture != IntPtr.Zero)
+ this.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false);
+
+ if (native->public_key != IntPtr.Zero) {
+ this.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key);
+ this.flags |= AssemblyNameFlags.PublicKey;
+ } else if (addPublickey) {
+ this.publicKey = EmptyArray<byte>.Value;
+ this.flags |= AssemblyNameFlags.PublicKey;
+ }
+
+ // MonoAssemblyName keeps the public key token as an hexadecimal string
+ if (native->public_key_token [0] != 0) {
+ byte[] keyToken = new byte [8];
+ for (int i = 0, j = 0; i < 8; ++i) {
+ keyToken [i] = (byte)(RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]) << 4);
+ keyToken [i] |= (byte)RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]);
+ }
+ this.keyToken = keyToken;
+ } else if (defaultToken) {
+ this.keyToken = EmptyArray<byte>.Value;
+ }
+ }
+
+ internal static AssemblyName Create (Assembly assembly, bool fillCodebase)
+ {
+ AssemblyName aname = new AssemblyName ();
+ unsafe {
+ MonoAssemblyName *native = GetNativeName (assembly._mono_assembly);
+ aname.FillName (native, fillCodebase ? assembly.CodeBase : null, true, true, true);
+ }
+ return aname;
+ }
}
}
using System.Security.Policy;
using System.Security.Permissions;
+using Mono;
+
namespace System.Reflection {
abstract class RuntimeAssembly : Assembly
var _ = CodeBase; // this will ensure the Demand is made
}
#endif
-
- AssemblyName aname = new AssemblyName ();
- FillName (this, aname);
- return aname;
+ return AssemblyName.Create (this, true);
}
-
}
[ComVisible (true)]
GC.register_ephemeron_array (data);
}
+ ~ConditionalWeakTable ()
+ {
+ }
+
/*LOCKING: _lock must be held*/
void Rehash () {
uint newSize = (uint)HashHelpers.GetPrime ((data.Length << 1) | 1);
return field.GetValue(o);
}
- object[] inArgs = new object[] { Type.GetTypeFromHandle(typeHandle).FullName,
- field.Name };
+ string typeName = Type.GetTypeFromHandle(typeHandle).FullName;
+ string fieldName = field.Name;
+ object[] inArgs = new object[] { typeName,
+ fieldName };
object[] outArgsMsg = new object[1];
MethodInfo minfo = typeof(object).GetMethod("FieldGetter", BindingFlags.NonPublic | BindingFlags.Instance);
if (minfo == null)
throw exc;
return outArgs[0];
}
+
+ internal void StoreRemoteField (IntPtr classPtr, IntPtr fieldPtr, object arg) {
+ Mono.RuntimeClassHandle classHandle = new Mono.RuntimeClassHandle (classPtr);
+ RuntimeFieldHandle fieldHandle = new RuntimeFieldHandle (fieldPtr);
+ RuntimeTypeHandle typeHandle = classHandle.GetTypeHandle ();
+ FieldInfo field = FieldInfo.GetFieldFromHandle (fieldHandle);
+
+ if (InCurrentContext ()) {
+ object o = _rp._server;
+ field.SetValue (o, arg);
+ return;
+ }
+
+ string typeName = Type.GetTypeFromHandle (typeHandle).FullName;
+ string fieldName = field.Name;
+ object [] inArgs = new object[] { typeName,
+ fieldName,
+ arg };
+ MethodInfo minfo = typeof(object).GetMethod ("FieldSetter", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (minfo == null)
+ throw new MissingMethodException ("System.Object", "FieldSetter");
+
+ MonoMethodMessage msg = new MonoMethodMessage (minfo, inArgs, null);
+ object [] outArgs;
+ Exception exc;
+ RealProxy.PrivateInvoke (_rp, msg, out exc, out outArgs);
+ if (exc != null)
+ throw exc;
+ }
+
}
#pragma warning restore 169, 649
* of icalls, do not require an increment.
*/
#pragma warning disable 169
- private const int mono_corlib_version = 151;
+ private const int mono_corlib_version = 152;
#pragma warning restore 169
[ComVisible (true)]
Mono.Globalization.Unicode/Normalization.cs
Mono.Globalization.Unicode/NormalizationTableUtil.cs
Mono/Runtime.cs
-Mono/RuntimeStructs.cs
Mono/RuntimeHandles.cs
+Mono/RuntimeMarshal.cs
+Mono/RuntimeStructs.cs
Mono/SafeGPtrArrayHandle.cs
+Mono/SafeStringMarshal.cs
Mono/DataConverter.cs
Mono.Interop/ComInteropProxy.cs
Mono.Interop/IDispatch.cs
--- /dev/null
+// CS0163: Control cannot fall through from one case label `case 1:' to another
+// Line: 9
+
+public class Program
+{
+ public static void Main ()
+ {
+ switch (1) {
+ case 1: {}
+ default: {}
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1644: Feature `interpolated strings' cannot be used because it is not part of the C# 5.0 language specification
+// Line: 9
+// Compiler options: -langversion:5
+
+public class Program
+{
+ public static void Main()
+ {
+ var x = $"I should not compile";
+ }
+}
this.loc = child.Location;
}
+ public bool RequiresEmitWithAwait { get; set; }
+
public override bool ContainsEmitWithAwait ()
{
- return child.ContainsEmitWithAwait ();
+ return RequiresEmitWithAwait || child.ContainsEmitWithAwait ();
}
public override Expression CreateExpressionTree (ResolveContext ec)
return base_type;
}
- if (iface_exprs != null) {
+ if (iface_exprs != null && this is Interface) {
foreach (var iface in iface_exprs) {
// the interface might not have been resolved, prevents a crash, see #442144
if (iface == null)
interpolated_string
: INTERPOLATED_STRING interpolations INTERPOLATED_STRING_END
{
+ if (lang_version < LanguageVersion.V_6)
+ FeatureIsNotAvailable (GetLocation ($1), "interpolated strings");
+
$$ = new InterpolatedString ((StringLiteral) $1, (List<Expression>) $2, (StringLiteral) $3);
}
| INTERPOLATED_STRING_END
{
+ if (lang_version < LanguageVersion.V_6)
+ FeatureIsNotAvailable (GetLocation ($1), "interpolated strings");
+
$$ = new InterpolatedString ((StringLiteral) $1, null, null);
}
;
{
TypeSpec argument_type = a.Type;
+ //
+ // Exactly matching Expression phase
+ //
+
//
// If argument is an anonymous function
//
if (q != p) {
//
- // An inferred return type X exists for E in the context of that parameter list, and
- // the conversion from X to Y1 is better than the conversion from X to Y2
+ // An inferred return type X exists for E in the context of the parameter list, and
+ // an identity conversion exists from X to the return type of D
//
- argument_type = am.InferReturnType (ec, null, orig_q);
- if (argument_type == null) {
- // TODO: Can this be hit?
- return 1;
- }
+ var inferred_type = am.InferReturnType (ec, null, orig_q);
+ if (inferred_type != null) {
+ if (inferred_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
+ inferred_type = ec.BuiltinTypes.Object;
+
+ if (inferred_type == p)
+ return 1;
- if (argument_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
- argument_type = ec.BuiltinTypes.Object;
+ if (inferred_type == q)
+ return 2;
+ }
}
}
if (element == null)
return null;
- if (element is CompoundAssign.TargetExpression) {
- if (first_emit != null)
- throw new InternalErrorException ("Can only handle one mutator at a time");
- first_emit = element;
- element = first_emit_temp = new LocalTemporary (element.Type);
+ var te = element as CompoundAssign.TargetExpression;
+ if (te != null) {
+ for (int i = 1; i < initializers.Count; ++i) {
+ if (initializers [i].ContainsEmitWithAwait ()) {
+ te.RequiresEmitWithAwait = true;
+ break;
+ }
+ }
+
+ if (!te.RequiresEmitWithAwait) {
+ if (first_emit != null)
+ throw new InternalErrorException ("Can only handle one mutator at a time");
+ first_emit = element;
+ element = first_emit_temp = new LocalTemporary (element.Type);
+ }
}
return Convert.ImplicitConversionRequired (
continue;
}
- if (constant_label != null && constant_label != sl)
+ if (section_rc.IsUnreachable) {
+ //
+ // Common case. Previous label section end is unreachable as
+ // it ends with break, return, etc. For next section revert
+ // to reachable again unless we have constant switch block
+ //
+ section_rc = constant_label != null && constant_label != sl ?
+ Reachability.CreateUnreachable () :
+ new Reachability ();
+ } else if (prev_label != null) {
+ //
+ // Error case as control cannot fall through from one case label
+ //
+ sl.SectionStart = false;
+ s = new MissingBreak (prev_label);
+ s.MarkReachable (rc);
+ block.Statements.Insert (i - 1, s);
+ ++i;
+ } else if (constant_label != null && constant_label != sl) {
+ //
+ // Special case for the first unreachable label in constant
+ // switch block
+ //
section_rc = Reachability.CreateUnreachable ();
- else if (section_rc.IsUnreachable) {
- section_rc = new Reachability ();
- } else {
- if (prev_label != null) {
- sl.SectionStart = false;
- s = new MissingBreak (prev_label);
- s.MarkReachable (rc);
- block.Statements.Insert (i - 1, s);
- ++i;
- }
}
prev_label = sl;
--- /dev/null
+using System;
+
+public class MainClass
+{
+ static long? X<T> (T a1, Func<T, T?> a2) where T : struct
+ {
+ return 0;
+ }
+
+ static int? X<T> (T a1, Func<T, int?> a2)
+ {
+ return 0;
+ }
+
+ static double? X<T> (T a1, Func<T, double?> a2)
+ {
+ return null;
+ }
+
+ public static void Main ()
+ {
+ int? sum = X<int> (1, i => {
+ if (i > 0)
+ return i;
+
+ return null;
+ });
+
+
+ int? sum2 = X (1, i => {
+ if (i > 0)
+ return i;
+
+ return null;
+ });
+
+ }
+}
--- /dev/null
+namespace Example
+{
+ public class A : A.InnerInterface
+ {
+ public interface InnerInterface
+ {
+ }
+
+ public static void Main ()
+ {
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Threading.Tasks;
+
+public class Program
+{
+ string Data {
+ get {
+ return data;
+ }
+ set {
+ ++setter_called;
+ data = value;
+ }
+ }
+
+ int setter_called;
+ string data = "init-";
+
+ string this [string arg] {
+ get {
+ return i_data;
+ }
+ set {
+ ++i_setter_called;
+ i_data = value;
+ }
+ }
+
+ int i_setter_called;
+ string i_data = "init2-";
+
+ public static int Main()
+ {
+ var p = new Program ();
+ p.TestProperty ().Wait ();
+ if (p.data != "init-nxa123z") {
+ return 1;
+ }
+
+ if (p.setter_called != 1)
+ return 2;
+
+ p.TestIndexer ().Wait ();
+
+ if (p.i_data != "init2-nxa123z") {
+ return 3;
+ }
+
+ if (p.i_setter_called != 1)
+ return 4;
+
+ return 0;
+ }
+
+ async Task TestProperty ()
+ {
+ Data += "n" + await StringValue () + "a" + 123.ToString () + "z";
+ }
+
+ async Task TestIndexer ()
+ {
+ string arg = "foo";
+ this[arg] += "n" + await StringValue () + "a" + 123.ToString () + "z";
+ }
+
+ async Task<string> StringValue ()
+ {
+ await Task.Yield ();
+ return "x";
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="gtest-lambda-37.cs">
+ <type name="MainClass">
+ <method name="System.Nullable`1[System.Int64] X[T](T, System.Func`2[T,System.Nullable`1[T]])" attrs="145">
+ <size>16</size>
+ </method>
+ <method name="System.Nullable`1[System.Int32] X[T](T, System.Func`2[T,System.Nullable`1[System.Int32]])" attrs="145">
+ <size>15</size>
+ </method>
+ <method name="System.Nullable`1[System.Double] X[T](T, System.Func`2[T,System.Nullable`1[System.Double]])" attrs="145">
+ <size>18</size>
+ </method>
+ <method name="Void Main()" attrs="150">
+ <size>74</size>
+ </method>
+ <method name="System.Nullable`1[System.Int32] <Main>m__0(Int32)" attrs="145">
+ <size>37</size>
+ </method>
+ <method name="System.Nullable`1[System.Int32] <Main>m__1(Int32)" attrs="145">
+ <size>37</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-linq-01.cs">
<type name="from.C">
<method name="Void Main()" attrs="150">
</method>
</type>
</test>
+ <test name="test-938.cs">
+ <type name="Example.A">
+ <method name="Void Main()" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-94.cs">
<type name="Base">
<method name="Int32 IVehicle.Start()" attrs="481">
</method>
</type>
</test>
+ <test name="test-async-86.cs">
+ <type name="Program">
+ <method name="System.String get_Data()" attrs="2177">
+ <size>15</size>
+ </method>
+ <method name="Void set_Data(System.String)" attrs="2177">
+ <size>23</size>
+ </method>
+ <method name="System.String get_Item(System.String)" attrs="2177">
+ <size>15</size>
+ </method>
+ <method name="Void set_Item(System.String, System.String)" attrs="2177">
+ <size>23</size>
+ </method>
+ <method name="Int32 Main()" attrs="150">
+ <size>134</size>
+ </method>
+ <method name="System.Threading.Tasks.Task TestProperty()" attrs="129">
+ <size>41</size>
+ </method>
+ <method name="System.Threading.Tasks.Task TestIndexer()" attrs="129">
+ <size>41</size>
+ </method>
+ <method name="System.Threading.Tasks.Task`1[System.String] StringValue()" attrs="129">
+ <size>33</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>29</size>
+ </method>
+ </type>
+ <type name="Program+<TestProperty>c__async0">
+ <method name="Void MoveNext()" attrs="486">
+ <size>314</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ <type name="Program+<TestIndexer>c__async1">
+ <method name="Void MoveNext()" attrs="486">
+ <size>337</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ <type name="Program+<StringValue>c__async2">
+ <method name="Void MoveNext()" attrs="486">
+ <size>171</size>
+ </method>
+ <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+ <size>13</size>
+ </method>
+ </type>
+ </test>
<test name="test-cls-00.cs">
<type name="CLSCLass_6">
<method name="Void add_Disposed(Delegate)" attrs="2182">
{ "h|?|help",
"Show this message and exit.",
v => showHelp = v != null },
+ { "contract-api",
+ "Produces contract API with all members at each level of inheritance hierarchy",
+ v => FullAPISet = v != null },
};
var asms = options.Parse (args);
internal static bool AbiMode { get; private set; }
internal static bool FollowForwarders { get; private set; }
+ internal static bool FullAPISet { get; set; }
}
public class Utils {
members.Add (new ConstructorData (writer, ctors));
}
- PropertyDefinition[] properties = GetProperties (type);
+ PropertyDefinition[] properties = GetProperties (type, Driver.FullAPISet);
if (properties.Length > 0) {
Array.Sort (properties, PropertyDefinitionComparer.Default);
members.Add (new PropertyData (writer, properties));
members.Add (new EventData (writer, events));
}
- MethodDefinition [] methods = GetMethods (type);
+ MethodDefinition [] methods = GetMethods (type, Driver.FullAPISet);
if (methods.Length > 0) {
Array.Sort (methods, MethodDefinitionComparer.Default);
members.Add (new MethodData (writer, methods));
}
- internal static PropertyDefinition [] GetProperties (TypeDefinition type) {
- ArrayList list = new ArrayList ();
+ internal static PropertyDefinition [] GetProperties (TypeDefinition type, bool fullAPI) {
+ var list = new List<PropertyDefinition> ();
+
+ var t = type;
+ do {
+ var properties = t.Properties;//type.GetProperties (flags);
+ foreach (PropertyDefinition property in properties) {
+ MethodDefinition getMethod = property.GetMethod;
+ MethodDefinition setMethod = property.SetMethod;
- var properties = type.Properties;//type.GetProperties (flags);
- foreach (PropertyDefinition property in properties) {
- MethodDefinition getMethod = property.GetMethod;
- MethodDefinition setMethod = property.SetMethod;
+ bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod);
+ bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod);
- bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod);
- bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod);
+ // if neither the getter or setter should be documented, then
+ // skip the property
+ if (hasGetter || hasSetter) {
+
+ if (t != type && list.Any (l => l.Name == property.Name))
+ continue;
- // if neither the getter or setter should be documented, then
- // skip the property
- if (hasGetter || hasSetter) {
- list.Add (property);
+ list.Add (property);
+ }
}
- }
- return (PropertyDefinition []) list.ToArray (typeof (PropertyDefinition));
+ if (!fullAPI)
+ break;
+
+ if (t.IsInterface || t.IsEnum)
+ break;
+
+ if (t.BaseType == null || t.BaseType.FullName == "System.Object")
+ t = null;
+ else
+ t = t.BaseType.Resolve ();
+
+ } while (t != null);
+
+ return list.ToArray ();
}
- private MethodDefinition[] GetMethods (TypeDefinition type)
+ private MethodDefinition[] GetMethods (TypeDefinition type, bool fullAPI)
{
- ArrayList list = new ArrayList ();
+ var list = new List<MethodDefinition> ();
- var methods = type.Methods;//type.GetMethods (flags);
- foreach (MethodDefinition method in methods) {
- if (method.IsSpecialName && !method.Name.StartsWith ("op_", StringComparison.Ordinal))
- continue;
+ var t = type;
+ do {
+ var methods = t.Methods;//type.GetMethods (flags);
+ foreach (MethodDefinition method in methods) {
+ if (method.IsSpecialName && !method.Name.StartsWith ("op_", StringComparison.Ordinal))
+ continue;
- // we're only interested in public or protected members
- if (!MustDocumentMethod(method))
- continue;
+ // we're only interested in public or protected members
+ if (!MustDocumentMethod (method))
+ continue;
+
+ if (t == type && IsFinalizer (method)) {
+ string name = method.DeclaringType.Name;
+ int arity = name.IndexOf ('`');
+ if (arity > 0)
+ name = name.Substring (0, arity);
- if (IsFinalizer (method)) {
- string name = method.DeclaringType.Name;
- int arity = name.IndexOf ('`');
- if (arity > 0)
- name = name.Substring (0, arity);
+ method.Name = "~" + name;
+ }
+
+ // TODO: Better check
+ if (t != type && list.Any (l => l.DeclaringType != method.DeclaringType && l.Name == method.Name && l.Parameters.Count == method.Parameters.Count))
+ continue;
- method.Name = "~" + name;
+ list.Add (method);
}
- list.Add (method);
- }
+ if (!fullAPI)
+ break;
- return (MethodDefinition []) list.ToArray (typeof (MethodDefinition));
+ if (!t.IsInterface || t.IsEnum)
+ break;
+
+ if (t.BaseType == null || t.BaseType.FullName == "System.Object")
+ t = null;
+ else
+ t = t.BaseType.Resolve ();
+
+ } while (t != null);
+
+ return list.ToArray ();
}
static bool IsFinalizer (MethodDefinition method)
</type>
<type fullname="System.Runtime.Remoting.Proxies.TransparentProxy" preserve="fields">
<method name="LoadRemoteFieldNew" />
+ <method name="StoreRemoteField" />
</type>
<type fullname="System.Runtime.Remoting.RemotingServices">
<method name="SerializeCallData" />
if (tgtAbstract) {
change.AppendAdded ("abstract", true).Append (" ");
} else if (srcWord != tgtWord) {
- if (!tgtFinal)
- change.AppendModified (srcWord, tgtWord, breaking).Append (" ");
+ if (!tgtFinal) {
+ if (State.IgnoreVirtualChanges) {
+ change.HasIgnoredChanges = true;
+ } else {
+ change.AppendModified (srcWord, tgtWord, breaking).Append (" ");
+ }
+ }
} else if (tgtWord.Length > 0) {
change.Append (tgtWord).Append (" ");
} else if (srcWord.Length > 0) {
if (tgtFinal) {
change.Append ("final ");
} else {
- change.AppendRemoved ("final", false).Append (" "); // removing 'final' is not a breaking change.
+ if (srcVirtual && !tgtVirtual && State.IgnoreVirtualChanges) {
+ change.HasIgnoredChanges = true;
+ } else {
+ change.AppendRemoved ("final", false).Append (" "); // removing 'final' is not a breaking change.
+ }
}
} else {
if (tgtFinal && srcVirtual) {
{
struct _WapiHandle_file *file_handle;
gpointer handle;
- int thr_ret, fd;
+ int fd;
const gchar *name;
gboolean ok;
handle = GINT_TO_POINTER (fd);
- thr_ret = mono_os_mutex_lock (&stdhandle_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&stdhandle_mutex);
ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
(gpointer *)&file_handle);
}
done:
- thr_ret = mono_os_mutex_unlock (&stdhandle_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&stdhandle_mutex);
return(handle);
}
mono_process = (struct MonoProcess *) g_malloc0 (sizeof (struct MonoProcess));
mono_process->pid = pid;
mono_process->handle_count = 1;
- if (mono_os_sem_init (&mono_process->exit_sem, 0) != 0) {
- /* If we can't create the exit semaphore, we just don't add anything
- * to our list of mono processes. Waiting on the process will return
- * immediately. */
- g_warning ("%s: could not create exit semaphore for process.", strerror (errno));
- g_free (mono_process);
- } else {
- /* Keep the process handle artificially alive until the process
- * exits so that the information in the handle isn't lost. */
- mono_w32handle_ref (handle);
- mono_process->handle = handle;
+ mono_os_sem_init (&mono_process->exit_sem, 0);
- process_handle_data->mono_process = mono_process;
+ /* Keep the process handle artificially alive until the process
+ * exits so that the information in the handle isn't lost. */
+ mono_w32handle_ref (handle);
+ mono_process->handle = handle;
- mono_os_mutex_lock (&mono_processes_mutex);
- mono_process->next = mono_processes;
- mono_processes = mono_process;
- mono_os_mutex_unlock (&mono_processes_mutex);
- }
+ process_handle_data->mono_process = mono_process;
+
+ mono_os_mutex_lock (&mono_processes_mutex);
+ mono_process->next = mono_processes;
+ mono_processes = mono_process;
+ mono_os_mutex_unlock (&mono_processes_mutex);
if (process_info != NULL) {
process_info->hProcess = handle;
ret = mono_os_sem_wait (&mp->exit_sem, alertable ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
}
- if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): sem_timedwait failure: %s",
- __func__, handle, timeout, g_strerror (errno));
- /* Should we return a failure here? */
- }
-
- if (ret == 0) {
+ if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
/* Success, process has exited */
mono_os_sem_post (&mp->exit_sem);
break;
}
- if (timeout == 0) {
+ if (ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT (timeout = 0)", __func__, handle, timeout);
return WAIT_TIMEOUT;
}
return WAIT_TIMEOUT;
}
- if (alertable && _wapi_thread_cur_apc_pending ()) {
+ if (alertable && ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout);
return WAIT_IO_COMPLETION;
}
_wapi_shm_sem_lock (int sem)
{
DEBUGLOG ("%s: locking nosem %d", __func__, sem);
- return mono_os_mutex_lock (&noshm_sems[sem]);
+ mono_os_mutex_lock (&noshm_sems[sem]);
+ return 0;
}
int
_wapi_shm_sem_unlock (int sem)
{
DEBUGLOG ("%s: unlocking nosem %d", __func__, sem);
- return mono_os_mutex_unlock (&noshm_sems[sem]);
+ mono_os_mutex_unlock (&noshm_sems[sem]);
+ return 0;
}
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
-#define MONO_CORLIB_VERSION 151
+#define MONO_CORLIB_VERSION 152
typedef struct
{
#define WINFX_KEY "31bf3856ad364e35"
#define ECMA_KEY "b77a5c561934e089"
#define MSFINAL_KEY "b03f5f7f11d50a3a"
+#define COMPACTFRAMEWORK_KEY "969db8053d3322ac"
typedef struct {
const char *name;
} KeyRemapEntry;
static KeyRemapEntry key_remap_table[] = {
+ { "CustomMarshalers", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
{ "Microsoft.CSharp", WINFX_KEY, MSFINAL_KEY },
+ { "Microsoft.VisualBasic", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
{ "System", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.ComponentModel.Composition", WINFX_KEY, ECMA_KEY },
{ "System.ComponentModel.DataAnnotations", "ddd0da4d3e678217", WINFX_KEY },
{ "System.Core", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System.Core", COMPACTFRAMEWORK_KEY, ECMA_KEY },
+ { "System.Data", COMPACTFRAMEWORK_KEY, ECMA_KEY },
+ { "System.Data.DataSetExtensions", COMPACTFRAMEWORK_KEY, ECMA_KEY },
+ { "System.Drawing", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
+ { "System.Messaging", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
// FIXME: MS uses MSFINAL_KEY for .NET 4.5
{ "System.Net", SILVERLIGHT_KEY, MSFINAL_KEY },
{ "System.Numerics", WINFX_KEY, ECMA_KEY },
{ "System.Runtime.Serialization", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System.Runtime.Serialization", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.ServiceModel", WINFX_KEY, ECMA_KEY },
+ { "System.ServiceModel", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.ServiceModel.Web", SILVERLIGHT_KEY, WINFX_KEY },
+ { "System.Web.Services", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
{ "System.Windows", SILVERLIGHT_KEY, MSFINAL_KEY },
+ { "System.Windows.Forms", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.Xml", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System.Xml", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.Xml.Linq", WINFX_KEY, ECMA_KEY },
+ { "System.Xml.Linq", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.Xml.Serialization", WINFX_KEY, ECMA_KEY }
};
g_free ((void *) aname->name);
g_free ((void *) aname->culture);
g_free ((void *) aname->hash_value);
+ g_free ((guint8*) aname->public_key);
}
static gboolean
{
}
+void
+mono_gc_suspend_finalizers (void)
+{
+}
+
int
mono_gc_get_suspend_signal (void)
{
void mono_gc_add_memory_pressure (gint64 value);
MONO_API int mono_gc_register_root (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg);
void mono_gc_deregister_root (char* addr);
-void mono_gc_finalize_domain (MonoDomain *domain, volatile gboolean *suspend);
+void mono_gc_finalize_domain (MonoDomain *domain);
void mono_gc_run_finalize (void *obj, void *data);
void mono_gc_clear_domain (MonoDomain * domain);
+/* Signal early termination of finalizer processing inside the gc */
+void mono_gc_suspend_finalizers (void);
/*
#endif
typedef struct DomainFinalizationReq {
+ gint32 ref;
MonoDomain *domain;
- HANDLE done_event;
+ MonoCoopSem done;
} DomainFinalizationReq;
-static gboolean gc_disabled = FALSE;
+static gboolean gc_disabled;
-static gboolean finalizing_root_domain = FALSE;
+static gboolean finalizing_root_domain;
-gboolean log_finalizers = FALSE;
-gboolean mono_do_not_finalize = FALSE;
-gchar **mono_do_not_finalize_class_names = NULL;
+gboolean log_finalizers;
+gboolean mono_do_not_finalize;
+volatile gboolean suspend_finalizers;
+gchar **mono_do_not_finalize_class_names ;
#define mono_finalizer_lock() mono_coop_mutex_lock (&finalizer_mutex)
#define mono_finalizer_unlock() mono_coop_mutex_unlock (&finalizer_mutex)
static MonoCoopMutex finalizer_mutex;
static MonoCoopMutex reference_queue_mutex;
-static GSList *domains_to_finalize= NULL;
-static MonoMList *threads_to_finalize = NULL;
+static GSList *domains_to_finalize;
+static MonoMList *threads_to_finalize;
static gboolean finalizer_thread_exited;
/* Uses finalizer_mutex */
static MonoInternalThread *gc_thread;
+#ifdef TARGET_WIN32
+static HANDLE pending_done_event;
+#else
+static gboolean pending_done;
+static MonoCoopCond pending_done_cond;
+static MonoCoopMutex pending_done_mutex;
+#endif
+
static void object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*));
static void reference_queue_proccess_all (void);
static void mono_reference_queue_cleanup (void);
static void reference_queue_clear_for_domain (MonoDomain *domain);
-static HANDLE pending_done_event;
+
static guint32
guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
return result;
}
+typedef struct {
+ MonoCoopCond *cond;
+ MonoCoopMutex *mutex;
+} BreakCoopAlertableWaitUD;
+
+static inline void
+break_coop_alertable_wait (gpointer user_data)
+{
+ BreakCoopAlertableWaitUD *ud = (BreakCoopAlertableWaitUD*)user_data;
+
+ mono_coop_mutex_lock (ud->mutex);
+ mono_coop_cond_signal (ud->cond);
+ mono_coop_mutex_unlock (ud->mutex);
+}
+
+/*
+ * coop_cond_timedwait_alertable:
+ *
+ * Wait on COND/MUTEX. If ALERTABLE is non-null, the wait can be interrupted.
+ * In that case, *ALERTABLE will be set to TRUE, and 0 is returned.
+ */
+static inline gint
+coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 timeout_ms, gboolean *alertable)
+{
+ int res;
+
+ if (alertable) {
+ BreakCoopAlertableWaitUD ud;
+
+ *alertable = FALSE;
+ ud.cond = cond;
+ ud.mutex = mutex;
+ mono_thread_info_install_interrupt (break_coop_alertable_wait, &ud, alertable);
+ if (*alertable)
+ return 0;
+ }
+ res = mono_coop_cond_timedwait (cond, mutex, timeout_ms);
+ if (alertable) {
+ mono_thread_info_uninstall_interrupt (alertable);
+ if (*alertable)
+ return 0;
+ }
+ return res;
+}
+
static gboolean
add_thread_to_finalize (MonoInternalThread *thread, MonoError *error)
{
return is_ok (error);
}
-static volatile gboolean suspend_finalizers = FALSE;
/*
* actually, we might want to queue the finalize requests in a separate thread,
* but we need to be careful about the execution domain of the thread...
mono_domain_finalize (MonoDomain *domain, guint32 timeout)
{
DomainFinalizationReq *req;
- guint32 res;
- HANDLE done_event;
MonoInternalThread *thread = mono_thread_internal_current ();
+ gint res;
+ gboolean ret;
+ gint64 start;
#if defined(__native_client__)
return FALSE;
mono_gc_collect (mono_gc_max_generation ());
- done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
- if (done_event == NULL) {
- return FALSE;
- }
-
req = g_new0 (DomainFinalizationReq, 1);
+ req->ref = 2;
req->domain = domain;
- req->done_event = done_event;
+ mono_coop_sem_init (&req->done, 0);
if (domain == mono_get_root_domain ())
finalizing_root_domain = TRUE;
if (timeout == -1)
timeout = INFINITE;
+ if (timeout != INFINITE)
+ start = mono_msec_ticks ();
- while (TRUE) {
- res = guarded_wait (done_event, timeout, TRUE);
- /* printf ("WAIT RES: %d.\n", res); */
+ ret = TRUE;
- if (res == WAIT_IO_COMPLETION) {
- if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0)
- return FALSE;
- } else if (res == WAIT_TIMEOUT) {
- /* We leak the handle here */
- return FALSE;
+ for (;;) {
+ if (timeout == INFINITE) {
+ res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE);
} else {
+ gint64 elapsed = mono_msec_ticks () - start;
+ if (elapsed >= timeout) {
+ ret = FALSE;
+ break;
+ }
+
+ res = mono_coop_sem_timedwait (&req->done, timeout - elapsed, MONO_SEM_FLAGS_ALERTABLE);
+ }
+
+ if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
break;
+ } else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
+ if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) {
+ ret = FALSE;
+ break;
+ }
+ } else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
+ ret = FALSE;
+ break;
+ } else {
+ g_error ("%s: unknown result %d", __func__, res);
}
}
- CloseHandle (done_event);
+ if (!ret) {
+ /* Try removing the req from domains_to_finalize:
+ * - if it's not found: the domain is being finalized,
+ * so we the ref count is already decremented
+ * - if it's found: the domain is not yet being finalized,
+ * so we can safely decrement the ref */
+
+ gboolean found;
+
+ mono_finalizer_lock ();
+
+ found = g_slist_index (domains_to_finalize, req) != -1;
+ if (found)
+ domains_to_finalize = g_slist_remove (domains_to_finalize, req);
+
+ mono_finalizer_unlock ();
+
+ if (found) {
+ /* We have to decrement it wherever we
+ * remove it from domains_to_finalize */
+ if (InterlockedDecrement (&req->ref) != 1)
+ g_error ("%s: req->ref should be 1, as we are the first one to decrement it", __func__);
+ }
+
+ goto done;
+ }
if (domain == mono_get_root_domain ()) {
mono_threadpool_ms_cleanup ();
mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
- return TRUE;
+done:
+ if (InterlockedDecrement (&req->ref) == 0) {
+ mono_coop_sem_destroy (&req->done);
+ g_free (req);
+ }
+
+ return ret;
}
void
if (gc_thread == NULL)
return;
+#ifdef TARGET_WIN32
ResetEvent (pending_done_event);
mono_gc_finalize_notify ();
/* g_print ("Waiting for pending finalizers....\n"); */
guarded_wait (pending_done_event, INFINITE, TRUE);
/* g_print ("Done pending....\n"); */
+#else
+ gboolean alerted = FALSE;
+ mono_coop_mutex_lock (&pending_done_mutex);
+ pending_done = FALSE;
+ mono_gc_finalize_notify ();
+ while (!pending_done) {
+ coop_cond_timedwait_alertable (&pending_done_cond, &pending_done_mutex, INFINITE, &alerted);
+ if (alerted)
+ break;
+ }
+ mono_coop_mutex_unlock (&pending_done_mutex);
+#endif
}
void
}
static MonoCoopSem finalizer_sem;
-static volatile gboolean finished=FALSE;
+static volatile gboolean finished;
+/*
+ * mono_gc_finalize_notify:
+ *
+ * Notify the finalizer thread that finalizers etc.
+ * are available to be processed.
+ */
void
mono_gc_finalize_notify (void)
{
* Run the finalizers of all finalizable objects in req->domain.
*/
static void
-finalize_domain_objects (DomainFinalizationReq *req)
+finalize_domain_objects (void)
{
- MonoDomain *domain = req->domain;
+ DomainFinalizationReq *req = NULL;
+ MonoDomain *domain;
+
+ if (domains_to_finalize) {
+ mono_finalizer_lock ();
+ if (domains_to_finalize) {
+ req = (DomainFinalizationReq *)domains_to_finalize->data;
+ domains_to_finalize = g_slist_remove (domains_to_finalize, req);
+ }
+ mono_finalizer_unlock ();
+ }
+
+ if (!req)
+ return;
+
+ domain = req->domain;
/* Process finalizers which are already in the queue */
mono_gc_invoke_finalizers ();
g_ptr_array_free (objs, TRUE);
}
#elif defined(HAVE_SGEN_GC)
- mono_gc_finalize_domain (domain, &suspend_finalizers);
+ mono_gc_finalize_domain (domain);
mono_gc_invoke_finalizers ();
#endif
reference_queue_clear_for_domain (domain);
/* printf ("DONE.\n"); */
- SetEvent (req->done_event);
+ mono_coop_sem_post (&req->done);
- /* The event is closed in mono_domain_finalize if we get here */
- g_free (req);
+ if (InterlockedDecrement (&req->ref) == 0) {
+ /* mono_domain_finalize already returned, and
+ * doesn't hold a reference to req anymore. */
+ mono_coop_sem_destroy (&req->done);
+ g_free (req);
+ }
}
static guint32
finalizer_thread (gpointer unused)
{
MonoError error;
+ gboolean wait = TRUE;
+
mono_thread_set_name_internal (mono_thread_internal_current (), mono_string_new (mono_get_root_domain (), "Finalizer"), FALSE, &error);
mono_error_assert_ok (&error);
- gboolean wait = TRUE;
-
/* Register a hazard free queue pump callback */
mono_hazard_pointer_install_free_queue_size_callback (hazard_free_queue_is_too_big);
mono_attach_maybe_start ();
- if (domains_to_finalize) {
- mono_finalizer_lock ();
- if (domains_to_finalize) {
- DomainFinalizationReq *req = (DomainFinalizationReq *)domains_to_finalize->data;
- domains_to_finalize = g_slist_remove (domains_to_finalize, req);
- mono_finalizer_unlock ();
-
- finalize_domain_objects (req);
- } else {
- mono_finalizer_unlock ();
- }
- }
+ finalize_domain_objects ();
/* If finished == TRUE, mono_gc_cleanup has been called (from mono_runtime_cleanup),
* before the domain is unloaded.
hazard_free_queue_pump ();
/* Avoid posting the pending done event until there are pending finalizers */
- if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == 0) {
+ if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
/* Don't wait again at the start of the loop */
wait = FALSE;
} else {
+#ifdef TARGET_WIN32
SetEvent (pending_done_event);
+#else
+ mono_coop_mutex_lock (&pending_done_mutex);
+ pending_done = TRUE;
+ mono_coop_cond_signal (&pending_done_cond);
+ mono_coop_mutex_unlock (&pending_done_mutex);
+#endif
}
}
return;
}
+#ifdef TARGET_WIN32
pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
g_assert (pending_done_event);
+#else
+ mono_coop_cond_init (&pending_done_cond);
+ mono_coop_mutex_init (&pending_done_mutex);
+#endif
+
mono_coop_cond_init (&exited_cond);
mono_coop_sem_init (&finalizer_sem, 0);
/* Set a flag which the finalizer thread can check */
suspend_finalizers = TRUE;
+ mono_gc_suspend_finalizers ();
/* Try to abort the thread, in the hope that it is running managed code */
mono_thread_internal_abort (gc_thread);
ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1)
ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree)
+ICALL_TYPE(RTMARSHAL, "Mono.RuntimeMarshal", RTMARSHAL_1)
+ICALL(RTMARSHAL_1, "FreeAssemblyName", ves_icall_Mono_RuntimeMarshal_FreeAssemblyName)
+
+ICALL_TYPE(SAFESTRMARSHAL, "Mono.SafeStringMarshal", SAFESTRMARSHAL_1)
+ICALL(SAFESTRMARSHAL_1, "GFree", ves_icall_Mono_SafeStringMarshal_GFree)
+ICALL(SAFESTRMARSHAL_2, "StringToUtf8", ves_icall_Mono_SafeStringMarshal_StringToUtf8)
+
#ifndef PLATFORM_RO_FS
ICALL_TYPE(KPAIR, "Mono.Security.Cryptography.KeyPairPersistence", KPAIR_1)
ICALL(KPAIR_1, "_CanSecure", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure)
ICALL(OBJ_2, "InternalGetHashCode", mono_object_hash)
ICALL(OBJ_3, "MemberwiseClone", ves_icall_System_Object_MemberwiseClone)
-ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_1)
-ICALL(ASSEM_1, "FillName", ves_icall_System_Reflection_Assembly_FillName)
+ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_1a)
ICALL(ASSEM_1a, "GetAotId", ves_icall_System_Reflection_Assembly_GetAotId)
ICALL(ASSEM_2, "GetCallingAssembly", ves_icall_System_Reflection_Assembly_GetCallingAssembly)
ICALL(ASSEM_3, "GetEntryAssembly", ves_icall_System_Reflection_Assembly_GetEntryAssembly)
ICALL(ASSEM_25, "get_location", ves_icall_System_Reflection_Assembly_get_location)
ICALL(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_load_with_partial_name)
-ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_1)
-ICALL(ASSEMN_1, "ParseName", ves_icall_System_Reflection_AssemblyName_ParseName)
+ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0)
+ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName)
+ICALL(ASSEMN_3, "ParseAssemblyName", ves_icall_System_Reflection_AssemblyName_ParseAssemblyName)
ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token)
ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1)
ICALL(RT_10, "GetInterfaceMapData", ves_icall_RuntimeType_GetInterfaceMapData)
ICALL(RT_11, "GetInterfaces", ves_icall_RuntimeType_GetInterfaces)
ICALL(RT_12, "GetMethodsByName_native", ves_icall_RuntimeType_GetMethodsByName_native)
-ICALL(RT_13, "GetNestedTypes_internal", ves_icall_RuntimeType_GetNestedTypes)
+ICALL(RT_13, "GetNestedTypes_native", ves_icall_RuntimeType_GetNestedTypes_native)
ICALL(RT_14, "GetPacking", ves_icall_RuntimeType_GetPacking)
ICALL(RT_15, "GetPropertiesByName_native", ves_icall_RuntimeType_GetPropertiesByName_native)
ICALL(RT_16, "GetTypeCodeImplInternal", ves_icall_type_GetTypeCodeInternal)
}
ICALL_EXPORT void
-ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array, MonoBoolean freeSeg)
+ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
{
- g_ptr_array_free (ptr_array, freeSeg);
+ g_ptr_array_free (ptr_array, TRUE);
+}
+
+ICALL_EXPORT void
+ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
+{
+ g_free (c_str);
+}
+
+ICALL_EXPORT char*
+ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
+{
+ MonoError error;
+ char *res = mono_string_to_utf8_checked (s, &error);
+ mono_error_set_pending_exception (&error);
+ return res;
}
/* System.TypeCode */
};
ICALL_EXPORT GPtrArray*
-ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, MonoString *name, guint32 bflags)
+ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
{
MonoError error;
- MonoDomain *domain;
MonoClass *startklass, *klass;
int match;
gpointer iter;
- char *utf8_name = NULL;
int (*compare_func) (const char *s1, const char *s2) = NULL;
MonoClassField *field;
- domain = ((MonoObject *)type)->vtable->domain;
if (type->type->byref) {
return g_ptr_array_new ();
}
+ mono_error_init (&error);
+
+ compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
+
klass = startklass = mono_class_from_mono_type (type->type);
GPtrArray *ptr_array = g_ptr_array_sized_new (16);
handle_parent:
if (mono_class_has_failure (klass)) {
- mono_error_init (&error);
mono_error_set_for_class_failure (&error, klass);
goto fail;
}
if (!match)
continue;
- if (name != NULL) {
- if (utf8_name == NULL) {
- utf8_name = mono_string_to_utf8_checked (name, &error);
- if (!is_ok (&error))
- goto fail;
- compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
- }
-
- if (compare_func (mono_field_get_name (field), utf8_name))
+ if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
continue;
- }
g_ptr_array_add (ptr_array, field);
}
if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
goto handle_parent;
- if (utf8_name != NULL)
- g_free (utf8_name);
return ptr_array;
fail:
- g_ptr_array_free (ptr_array, FALSE);
+ g_ptr_array_free (ptr_array, TRUE);
mono_error_set_pending_exception (&error);
return NULL;
}
}
ICALL_EXPORT GPtrArray*
-ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case)
+ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
{
MonoError error;
- MonoDomain *domain;
- const char *mname = NULL;
GPtrArray *method_array;
MonoClass *klass;
klass = mono_class_from_mono_type (type->type);
- domain = ((MonoObject *)type)->vtable->domain;
if (type->type->byref) {
return g_ptr_array_new ();
}
- if (name) {
- mname = mono_string_to_utf8_checked (name, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
- }
-
method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
- g_free ((char*)mname);
mono_error_set_pending_exception (&error);
return method_array;
}
}
ICALL_EXPORT GPtrArray*
-ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case)
+ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
{
MonoError error;
MonoClass *startklass, *klass;
MonoProperty *prop;
int match;
guint32 flags;
- gchar *propname = NULL;
int (*compare_func) (const char *s1, const char *s2) = NULL;
gpointer iter;
GHashTable *properties = NULL;
klass = startklass = mono_class_from_mono_type (type->type);
- if (name != NULL) {
- propname = mono_string_to_utf8_checked (name, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
- compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
- }
+ compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
handle_parent:
mono_class_setup_methods (klass);
mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass))
+ if (mono_class_has_failure (klass)) {
+ mono_error_set_for_class_failure (&error, klass);
goto loader_error;
+ }
iter = NULL;
while ((prop = mono_class_get_properties (klass, &iter))) {
continue;
match = 0;
- if (name != NULL) {
- if (compare_func (propname, prop->name))
- continue;
- }
+ if (propname != NULL && compare_func (propname, prop->name))
+ continue;
if (g_hash_table_lookup (properties, prop))
continue;
goto handle_parent;
g_hash_table_destroy (properties);
- g_free (propname);
return res_array;
loader_error:
- if (mono_class_has_failure (klass))
- mono_error_set_for_class_failure (&error, klass);
-
if (properties)
g_hash_table_destroy (properties);
- if (name)
- g_free (propname);
- g_ptr_array_free (res_array, FALSE);
+ g_ptr_array_free (res_array, TRUE);
mono_error_set_pending_exception (&error);
}
ICALL_EXPORT GPtrArray*
-ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, MonoString *name, guint32 bflags)
+ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
{
MonoError error;
MonoClass *startklass, *klass;
MonoEvent *event;
int match;
gpointer iter;
- char *utf8_name = NULL;
int (*compare_func) (const char *s1, const char *s2) = NULL;
GHashTable *events = NULL;
GPtrArray *res_array;
mono_error_init (&error);
+ compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
+
res_array = g_ptr_array_sized_new (4);
klass = startklass = mono_class_from_mono_type (type->type);
handle_parent:
mono_class_setup_methods (klass);
mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass))
- goto loader_error;
+ if (mono_class_has_failure (klass)) {
+ mono_error_set_for_class_failure (&error, klass);
+ goto failure;
+ }
iter = NULL;
while ((event = mono_class_get_events (klass, &iter))) {
if (!match)
continue;
- if (name != NULL) {
- if (utf8_name == NULL) {
- utf8_name = mono_string_to_utf8_checked (name, &error);
- if (!is_ok (&error))
- goto failure;
- compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
- }
-
- if (compare_func (event->name, utf8_name))
- continue;
- }
+ if (utf8_name != NULL && compare_func (event->name, utf8_name))
+ continue;
if (g_hash_table_lookup (events, event))
continue;
g_hash_table_destroy (events);
- if (utf8_name != NULL)
- g_free (utf8_name);
-
return res_array;
-loader_error:
- if (mono_class_has_failure (klass))
- mono_error_set_for_class_failure (&error, klass);
-
failure:
-
if (events != NULL)
g_hash_table_destroy (events);
- if (utf8_name != NULL)
- g_free (utf8_name);
- g_ptr_array_free (res_array, FALSE);
+ g_ptr_array_free (res_array, TRUE);
mono_error_set_pending_exception (&error);
return NULL;
}
-ICALL_EXPORT MonoArray*
-ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
+ICALL_EXPORT GPtrArray *
+ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
{
- MonoError error;
- MonoReflectionType *rt;
- MonoDomain *domain;
MonoClass *klass;
- MonoArray *res = NULL;
- int i, match;
+ int match;
MonoClass *nested;
gpointer iter;
- char *str = NULL;
- MonoPtrArray tmp_array;
-
- mono_error_init (&error);
+ GPtrArray *res_array;
- domain = ((MonoObject *)type)->vtable->domain;
if (type->type->byref) {
- MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
- mono_error_set_pending_exception (&error);
- return result;
+ return g_ptr_array_new ();
}
+
klass = mono_class_from_mono_type (type->type);
/*
if (klass->generic_class)
klass = klass->generic_class->container_class;
- mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
+ res_array = g_ptr_array_new ();
+
iter = NULL;
while ((nested = mono_class_get_nested_types (klass, &iter))) {
match = 0;
if (!match)
continue;
- if (name != NULL) {
- if (str == NULL) {
- str = mono_string_to_utf8_checked (name, &error);
- if (!is_ok (&error))
- goto leave;
- mono_identifier_unescape_type_name_chars (str);
- }
-
- if (strcmp (nested->name, str))
+ if (str != NULL && strcmp (nested->name, str))
continue;
- }
-
- rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
- if (!is_ok (&error))
- goto leave;
- mono_ptr_array_append (tmp_array, (MonoObject*) rt);
+ g_ptr_array_add (res_array, &nested->byval_arg);
}
- res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
- if (!is_ok (&error))
- goto leave;
-
- for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
- mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
-
-leave:
- mono_ptr_array_destroy (tmp_array);
-
- g_free (str);
-
- mono_error_set_pending_exception (&error);
- return res;
+ return res_array;
}
ICALL_EXPORT MonoReflectionType*
return res;
}
-ICALL_EXPORT void
-ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
+ICALL_EXPORT MonoAssemblyName *
+ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
{
- MonoError error;
- gchar *absolute, *dirname;
- MonoAssembly *mass = assembly->assembly;
-
- /* XXX this is duplicated code to compute the codebase URI, unify it */
- if (g_path_is_absolute (mass->image->name)) {
- absolute = g_strdup (mass->image->name);
- dirname = g_path_get_dirname (absolute);
- } else {
- absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
- dirname = g_strdup (mass->basedir);
- }
-
- replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
- g_free (dirname);
-
- fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
- mono_error_set_pending_exception (&error);
-
- g_free (absolute);
+ return &mass->aname;
}
ICALL_EXPORT void
return res;
}
-ICALL_EXPORT gboolean
-ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
+ICALL_EXPORT void
+ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
{
- MonoError error;
- MonoAssemblyName aname;
- MonoDomain *domain = mono_object_domain (name);
- char *val;
- gboolean is_version_defined;
- gboolean is_token_defined;
-
- aname.public_key = NULL;
- val = mono_string_to_utf8_checked (assname, &error);
- if (mono_error_set_pending_exception (&error))
- return FALSE;
-
- if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
- g_free ((guint8*) aname.public_key);
- g_free (val);
- return FALSE;
- }
-
- fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
- mono_error_set_pending_exception (&error);
+ mono_assembly_name_free (aname);
+}
- mono_assembly_name_free (&aname);
- g_free ((guint8*) aname.public_key);
- g_free (val);
+ICALL_EXPORT gboolean
+ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
+{
+ *is_version_definited = *is_token_defined = FALSE;
- return TRUE;
+ return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
}
ICALL_EXPORT MonoReflectionType*
write_sleb128 (lne->il_offset, ptr, &ptr);
write_sleb128 (lne->native_offset, ptr, &ptr);
}
-
- *ptr++ = jit->this_var ? 1 : 0;
- if (jit->this_var)
- write_variable (jit->this_var, ptr, &ptr);
-
- write_leb128 (jit->num_params, ptr, &ptr);
- for (i = 0; i < jit->num_params; i++)
- write_variable (&jit->params [i], ptr, &ptr);
-
- write_leb128 (jit->num_locals, ptr, &ptr);
- for (i = 0; i < jit->num_locals; i++)
- write_variable (&jit->locals [i], ptr, &ptr);
-
- *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
- if (jit->gsharedvt_info_var) {
- write_variable (jit->gsharedvt_info_var, ptr, &ptr);
- write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+ write_leb128 (jit->has_var_info, ptr, &ptr);
+ if (jit->has_var_info) {
+ *ptr++ = jit->this_var ? 1 : 0;
+ if (jit->this_var)
+ write_variable (jit->this_var, ptr, &ptr);
+
+ write_leb128 (jit->num_params, ptr, &ptr);
+ for (i = 0; i < jit->num_params; i++)
+ write_variable (&jit->params [i], ptr, &ptr);
+
+ write_leb128 (jit->num_locals, ptr, &ptr);
+ for (i = 0; i < jit->num_locals; i++)
+ write_variable (&jit->locals [i], ptr, &ptr);
+
+ *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
+ if (jit->gsharedvt_info_var) {
+ write_variable (jit->gsharedvt_info_var, ptr, &ptr);
+ write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+ }
}
size = ptr - oldptr;
lne->il_offset = read_sleb128 (ptr, &ptr);
lne->native_offset = read_sleb128 (ptr, &ptr);
}
+ jit->has_var_info = read_leb128 (ptr, &ptr);
+ if (jit->has_var_info) {
+ if (*ptr++) {
+ jit->this_var = g_new0 (MonoDebugVarInfo, 1);
+ read_variable (jit->this_var, ptr, &ptr);
+ }
- if (*ptr++) {
- jit->this_var = g_new0 (MonoDebugVarInfo, 1);
- read_variable (jit->this_var, ptr, &ptr);
- }
-
- jit->num_params = read_leb128 (ptr, &ptr);
- jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
- for (i = 0; i < jit->num_params; i++)
- read_variable (&jit->params [i], ptr, &ptr);
-
- jit->num_locals = read_leb128 (ptr, &ptr);
- jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
- for (i = 0; i < jit->num_locals; i++)
- read_variable (&jit->locals [i], ptr, &ptr);
-
- if (*ptr++) {
- jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
- jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
- read_variable (jit->gsharedvt_info_var, ptr, &ptr);
- read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+ jit->num_params = read_leb128 (ptr, &ptr);
+ jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
+ for (i = 0; i < jit->num_params; i++)
+ read_variable (&jit->params [i], ptr, &ptr);
+
+ jit->num_locals = read_leb128 (ptr, &ptr);
+ jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
+ for (i = 0; i < jit->num_locals; i++)
+ read_variable (&jit->locals [i], ptr, &ptr);
+
+ if (*ptr++) {
+ jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
+ jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
+ read_variable (jit->gsharedvt_info_var, ptr, &ptr);
+ read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+ }
}
return jit;
const mono_byte *wrapper_addr;
uint32_t num_line_numbers;
MonoDebugLineNumberEntry *line_numbers;
+ uint32_t has_var_info;
uint32_t num_params;
MonoDebugVarInfo *this_var;
MonoDebugVarInfo *params;
{
}
+void
+mono_gc_suspend_finalizers (void)
+{
+}
+
int
mono_gc_get_suspend_signal (void)
{
gboolean
mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, void* val, MonoError *error);
-void
-mono_store_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg);
-
gboolean
mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg, MonoError *error);
MONO_REQ_GC_UNSAFE_MODE;
- static MonoMethod *setter = NULL;
+ mono_error_init (error);
MonoDomain *domain = mono_domain_get ();
- MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
MonoClass *field_class;
- MonoMethodMessage *msg;
- MonoArray *out_args;
- MonoObject *exc;
MonoObject *arg;
- char* full_name;
-
- mono_error_init (error);
g_assert (mono_object_is_transparent_proxy (this_obj));
field_class = mono_class_from_mono_type (field->type);
- if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
- if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
- else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
- return TRUE;
- }
-
- if (!setter) {
- setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
- if (!setter) {
- mono_error_set_not_supported (error, "Linked away.");
- return FALSE;
- }
- }
-
if (field_class->valuetype) {
arg = mono_value_box_checked (domain, field_class, val, error);
return_val_if_nok (error, FALSE);
- } else
- arg = *((MonoObject **)val);
-
-
- msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
- return_val_if_nok (error, FALSE);
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error);
- return_val_if_nok (error, FALSE);
- mono_message_init (domain, msg, rm, NULL, error);
- return_val_if_nok (error, FALSE);
-
- full_name = mono_type_get_full_name (klass);
- mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
- mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
- mono_array_setref (msg->args, 2, arg);
- g_free (full_name);
-
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
- return_val_if_nok (error, FALSE);
-
- if (exc) {
- mono_error_set_exception_instance (error, (MonoException *)exc);
- return FALSE;
+ } else {
+ arg = *((MonoObject**)val);
}
- return TRUE;
+
+ return mono_store_remote_field_new_checked (this_obj, klass, field, arg, error);
}
/**
mono_error_cleanup (&error);
}
-/**
- * mono_store_remote_field_new_icall:
- * @this_obj:
- * @klass:
- * @field:
- * @arg:
- *
- * Missing documentation
- */
-void
-mono_store_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg)
-{
- MonoError error;
- (void) mono_store_remote_field_new_checked (this_obj, klass, field, arg, &error);
- mono_error_set_pending_exception (&error);
-}
-
/**
* mono_store_remote_field_new_checked:
* @this_obj:
{
MONO_REQ_GC_UNSAFE_MODE;
- static MonoMethod *setter = NULL;
- MonoDomain *domain = mono_domain_get ();
- MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
- MonoClass *field_class;
- MonoMethodMessage *msg;
- MonoArray *out_args;
- MonoObject *exc;
- char* full_name;
+ static MonoMethod *tp_store = NULL;
mono_error_init (error);
g_assert (mono_object_is_transparent_proxy (this_obj));
- field_class = mono_class_from_mono_type (field->type);
-
- if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
- if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
- else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
- return TRUE;
- }
-
- if (!setter) {
- setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
- if (!setter) {
+ if (!tp_store) {
+ tp_store = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1);
+ if (!tp_store) {
mono_error_set_not_supported (error, "Linked away.");
return FALSE;
}
}
- msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
- return_val_if_nok (error, FALSE);
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error);
- return_val_if_nok (error, FALSE);
- mono_message_init (domain, msg, rm, NULL, error);
- return_val_if_nok (error, FALSE);
-
- full_name = mono_type_get_full_name (klass);
- mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
- mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
- mono_array_setref (msg->args, 2, arg);
- g_free (full_name);
-
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
- return_val_if_nok (error, FALSE);
+ gpointer args[3];
+ args [0] = &klass;
+ args [1] = &field;
+ args [2] = arg;
- if (exc) {
- mono_error_set_exception_instance (error, (MonoException *)exc);
- return FALSE;
- }
- return TRUE;
+ mono_runtime_invoke_checked (tp_store, this_obj, args, error);
+ return is_ok (error);
}
#endif
register_icall (mono_remoting_wrapper, "mono_remoting_wrapper", "object ptr ptr", FALSE);
register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE);
register_icall (mono_compile_method_icall, "mono_compile_method_icall", "ptr ptr", FALSE);
- /* mono_store_remote_field_new_icall registered by mini-runtime.c */
}
return res;
}
-/*
- * mono_marshal_get_stfld_remote_wrapper:
- * klass: The type of the field
- *
- * This function generates a wrapper for calling mono_store_remote_field_new
- * with the appropriate signature.
- * Similarly to mono_marshal_get_ldfld_remote_wrapper () this doesn't depend on the
- * klass argument anymore.
- */
-MonoMethod *
-mono_marshal_get_stfld_remote_wrapper (MonoClass *klass)
-{
- MonoMethodSignature *sig;
- MonoMethodBuilder *mb;
- MonoMethod *res;
- static MonoMethod *cached = NULL;
-
- mono_marshal_lock_internal ();
- if (cached) {
- mono_marshal_unlock_internal ();
- return cached;
- }
- mono_marshal_unlock_internal ();
-
- mb = mono_mb_new_no_dup_name (mono_defaults.object_class, "__mono_store_remote_field_new_wrapper", MONO_WRAPPER_STFLD_REMOTE);
-
- mb->method->save_lmf = 1;
-
- sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
- sig->params [0] = &mono_defaults.object_class->byval_arg;
- sig->params [1] = &mono_defaults.int_class->byval_arg;
- sig->params [2] = &mono_defaults.int_class->byval_arg;
- sig->params [3] = &mono_defaults.object_class->byval_arg;
- sig->ret = &mono_defaults.void_class->byval_arg;
-
-#ifndef DISABLE_JIT
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_ldarg (mb, 2);
- mono_mb_emit_ldarg (mb, 3);
-
- mono_mb_emit_icall (mb, mono_store_remote_field_new_icall);
-
- mono_mb_emit_byte (mb, CEE_RET);
-#endif
-
- mono_marshal_lock_internal ();
- res = cached;
- mono_marshal_unlock_internal ();
- if (!res) {
- MonoMethod *newm;
- newm = mono_mb_create (mb, sig, 6, NULL);
- mono_marshal_lock_internal ();
- res = cached;
- if (!res) {
- res = newm;
- cached = res;
- mono_marshal_unlock_internal ();
- } else {
- mono_marshal_unlock_internal ();
- mono_free_method (newm);
- }
- }
- mono_mb_free (mb);
-
- return res;
-}
/*
* mono_marshal_get_stfld_wrapper:
WrapperInfo *info;
char *name;
int t, pos;
+ static MonoMethod *tp_store = NULL;
type = mono_type_get_underlying_type (type);
t = type->type;
if ((res = mono_marshal_find_in_cache (cache, klass)))
return res;
+#ifndef DISABLE_REMOTING
+ if (!tp_store) {
+ tp_store = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1);
+ g_assert (tp_store != NULL);
+ }
+#endif
+
/* we add the %p pointer value of klass because class names are not unique */
name = g_strdup_printf ("__stfld_wrapper_%p_%s.%s", klass, klass->name_space, klass->name);
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
mono_mb_emit_ldarg (mb, 0);
pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
+#ifndef DISABLE_REMOTING
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldarg (mb, 1);
mono_mb_emit_ldarg (mb, 2);
if (klass->valuetype)
mono_mb_emit_op (mb, CEE_BOX, klass);
- mono_mb_emit_managed_call (mb, mono_marshal_get_stfld_remote_wrapper (klass), NULL);
+ mono_mb_emit_managed_call (mb, tp_store, NULL);
mono_mb_emit_byte (mb, CEE_RET);
+#endif
mono_mb_patch_branch (mb, pos);
MonoMethod *
mono_marshal_get_ldflda_wrapper (MonoType *type);
-MonoMethod *
-mono_marshal_get_ldfld_remote_wrapper (MonoClass *klass);
-
-MonoMethod *
-mono_marshal_get_stfld_remote_wrapper (MonoClass *klass);
-
MonoMethod *
mono_marshal_get_proxy_cancast (MonoClass *klass);
HEAVY_STAT (++stat_wbarrier_object_copy);
- if (sgen_ptr_in_nursery (obj) || ptr_on_stack (obj) || !SGEN_OBJECT_HAS_REFERENCES (src)) {
+ SGEN_ASSERT (6, !ptr_on_stack (obj), "Why is this called for a non-reference type?");
+ if (sgen_ptr_in_nursery (obj) || !SGEN_OBJECT_HAS_REFERENCES (src)) {
size = mono_object_class (obj)->instance_size;
mono_gc_memmove_aligned ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject),
size - sizeof (MonoObject));
* @suspend is used for early termination of the enqueuing process.
*/
void
-mono_gc_finalize_domain (MonoDomain *domain, volatile gboolean *suspend)
+mono_gc_finalize_domain (MonoDomain *domain)
{
- sgen_finalize_if (object_in_domain_predicate, domain, suspend);
+ sgen_finalize_if (object_in_domain_predicate, domain);
+}
+
+void
+mono_gc_suspend_finalizers (void)
+{
+ sgen_set_suspend_finalizers ();
}
/*
if (retire)
retire = FALSE;
+ /* The tpdomain->domain might have unloaded, while this thread was parked */
+ previous_tpdomain = NULL;
+
continue;
}
args [0] = start_arg;
/* we may want to handle the exception here. See comment below on unhandled exceptions */
mono_runtime_delegate_invoke_checked (start_delegate, args, &error);
- mono_error_raise_exception (&error); /* OK, triggers unhandled exn handler */
+
+ if (!mono_error_ok (&error)) {
+ MonoException *ex = mono_error_convert_to_exception (&error);
+ if (ex)
+ mono_unhandled_exception (&ex->object);
+ } else {
+ mono_error_cleanup (&error);
+ }
}
/* If the thread calls ExitThread at all, this remaining code
wait->num++;
THREAD_DEBUG (g_print ("%s: Aborting id: %"G_GSIZE_FORMAT"\n", __func__, (gsize)thread->tid));
- mono_thread_internal_stop (thread);
+ mono_thread_internal_abort (thread);
return TRUE;
}
WRAPPER(XDOMAIN_DISPATCH, "xdomain-dispatch")
WRAPPER(LDFLD, "ldfld")
WRAPPER(STFLD, "stfld")
-WRAPPER(STFLD_REMOTE, "stfld-remote")
WRAPPER(SYNCHRONIZED, "synchronized")
WRAPPER(DYNAMIC_METHOD, "dynamic-method")
WRAPPER(ISINST, "isinst")
encode_klass_ref (acfg, info->d.proxy.klass, p, &p);
break;
}
- case MONO_WRAPPER_STFLD_REMOTE:
- break;
case MONO_WRAPPER_ALLOC: {
/* The GC name is saved once in MonoAotFileInfo */
g_assert (info->d.alloc.alloc_type != -1);
case MONO_WRAPPER_STFLD:
case MONO_WRAPPER_LDFLD:
case MONO_WRAPPER_LDFLDA:
- case MONO_WRAPPER_STFLD_REMOTE:
case MONO_WRAPPER_STELEMREF:
case MONO_WRAPPER_ISINST:
case MONO_WRAPPER_PROXY_ISINST:
}
break;
}
- case MONO_WRAPPER_STFLD_REMOTE:
- ref->method = mono_marshal_get_stfld_remote_wrapper (NULL);
- break;
#endif
case MONO_WRAPPER_ALLOC: {
int atype = decode_value (p, &p);
jit->code_start = cfg->native_code;
jit->epilogue_begin = cfg->epilog_begin;
jit->code_size = cfg->code_len;
+ jit->has_var_info = debug_options.mdb_optimizations != 0;
if (jit->epilogue_begin)
record_line_number (info, jit->epilogue_begin, header->code_size);
- jit->num_params = sig->param_count;
- jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
+ if (jit->has_var_info) {
+ jit->num_params = sig->param_count;
+ jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
- for (i = 0; i < jit->num_locals; i++)
- write_variable (cfg->locals [i], &jit->locals [i]);
+ for (i = 0; i < jit->num_locals; i++)
+ write_variable (cfg->locals [i], &jit->locals [i]);
- if (sig->hasthis) {
- jit->this_var = g_new0 (MonoDebugVarInfo, 1);
- write_variable (cfg->args [0], jit->this_var);
- }
+ if (sig->hasthis) {
+ jit->this_var = g_new0 (MonoDebugVarInfo, 1);
+ write_variable (cfg->args [0], jit->this_var);
+ }
- for (i = 0; i < jit->num_params; i++)
- write_variable (cfg->args [i + sig->hasthis], &jit->params [i]);
+ for (i = 0; i < jit->num_params; i++)
+ write_variable (cfg->args [i + sig->hasthis], &jit->params [i]);
- if (cfg->gsharedvt_info_var) {
- jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
- jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
- write_variable (cfg->gsharedvt_info_var, jit->gsharedvt_info_var);
- write_variable (cfg->gsharedvt_locals_var, jit->gsharedvt_locals_var);
+ if (cfg->gsharedvt_info_var) {
+ jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
+ jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
+ write_variable (cfg->gsharedvt_info_var, jit->gsharedvt_info_var);
+ write_variable (cfg->gsharedvt_locals_var, jit->gsharedvt_locals_var);
+ }
}
jit->num_line_numbers = info->line_numbers->len;
encode_value (jit->epilogue_begin, p, &p);
encode_value (jit->prologue_end, p, &p);
encode_value (jit->code_size, p, &p);
+ encode_value (jit->has_var_info, p, &p);
- for (i = 0; i < jit->num_params; ++i)
- serialize_variable (&jit->params [i], p, &p);
+ if (jit->has_var_info) {
+ for (i = 0; i < jit->num_params; ++i)
+ serialize_variable (&jit->params [i], p, &p);
- if (mono_method_signature (cfg->method)->hasthis)
- serialize_variable (jit->this_var, p, &p);
+ if (jit->this_var)
+ serialize_variable (jit->this_var, p, &p);
- for (i = 0; i < jit->num_locals; i++)
- serialize_variable (&jit->locals [i], p, &p);
+ for (i = 0; i < jit->num_locals; i++)
+ serialize_variable (&jit->locals [i], p, &p);
- if (jit->gsharedvt_info_var) {
- encode_value (1, p, &p);
- serialize_variable (jit->gsharedvt_info_var, p, &p);
- serialize_variable (jit->gsharedvt_locals_var, p, &p);
- } else {
- encode_value (0, p, &p);
+ if (jit->gsharedvt_info_var) {
+ encode_value (1, p, &p);
+ serialize_variable (jit->gsharedvt_info_var, p, &p);
+ serialize_variable (jit->gsharedvt_locals_var, p, &p);
+ } else {
+ encode_value (0, p, &p);
+ }
}
encode_value (jit->num_line_numbers, p, &p);
jit = g_new0 (MonoDebugMethodJitInfo, 1);
jit->code_start = code_start;
- jit->num_locals = header->num_locals;
- jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
- jit->num_params = mono_method_signature (method)->param_count;
- jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
p = buf;
jit->epilogue_begin = decode_value (p, &p);
jit->prologue_end = decode_value (p, &p);
jit->code_size = decode_value (p, &p);
+ jit->has_var_info = decode_value (p, &p);
- for (i = 0; i < jit->num_params; ++i)
- deserialize_variable (&jit->params [i], p, &p);
+ if (jit->has_var_info) {
+ jit->num_locals = header->num_locals;
+ jit->num_params = mono_method_signature (method)->param_count;
+ jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
+ jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
- if (mono_method_signature (method)->hasthis) {
- jit->this_var = g_new0 (MonoDebugVarInfo, 1);
- deserialize_variable (jit->this_var, p, &p);
- }
+ for (i = 0; i < jit->num_params; ++i)
+ deserialize_variable (&jit->params [i], p, &p);
- for (i = 0; i < jit->num_locals; i++)
- deserialize_variable (&jit->locals [i], p, &p);
+ if (mono_method_signature (method)->hasthis) {
+ jit->this_var = g_new0 (MonoDebugVarInfo, 1);
+ deserialize_variable (jit->this_var, p, &p);
+ }
+
+ for (i = 0; i < jit->num_locals; i++)
+ deserialize_variable (&jit->locals [i], p, &p);
- if (decode_value (p, &p)) {
- jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
- jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
- deserialize_variable (jit->gsharedvt_info_var, p, &p);
- deserialize_variable (jit->gsharedvt_locals_var, p, &p);
+ if (decode_value (p, &p)) {
+ jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
+ jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
+ deserialize_variable (jit->gsharedvt_info_var, p, &p);
+ deserialize_variable (jit->gsharedvt_locals_var, p, &p);
+ }
}
jit->num_line_numbers = decode_value (p, &p);
static void
resume_vm (void)
{
- int err;
-
g_assert (is_debugger_thread ());
mono_loader_lock ();
}
/* Signal this even when suspend_count > 0, since some threads might have resume_count > 0 */
- err = mono_coop_cond_broadcast (&suspend_cond);
- g_assert (err == 0);
+ mono_coop_cond_broadcast (&suspend_cond);
mono_coop_mutex_unlock (&suspend_mutex);
//g_assert (err == 0);
static void
resume_thread (MonoInternalThread *thread)
{
- int err;
DebuggerTlsData *tls;
g_assert (is_debugger_thread ());
* Signal suspend_count without decreasing suspend_count, the threads will wake up
* but only the one whose resume_count field is > 0 will be resumed.
*/
- err = mono_coop_cond_broadcast (&suspend_cond);
- g_assert (err == 0);
+ mono_coop_cond_broadcast (&suspend_cond);
mono_coop_mutex_unlock (&suspend_mutex);
//g_assert (err == 0);
suspend_current (void)
{
DebuggerTlsData *tls;
- int err;
g_assert (!is_debugger_thread ());
DEBUG_PRINTF (1, "[%p] Suspended.\n", (gpointer) (gsize) mono_native_thread_id_get ());
while (suspend_count - tls->resume_count > 0) {
- err = mono_coop_cond_wait (&suspend_cond, &suspend_mutex);
- g_assert (err == 0);
+ mono_coop_cond_wait (&suspend_cond, &suspend_mutex);
}
tls->suspended = FALSE;
MonoError oerror;
/* Might be AOTed code */
+ mono_class_init (method->klass);
code = mono_aot_get_method_checked (domain, method, &oerror);
g_assert (code);
mono_error_assert_ok (&oerror);
sig = mono_method_signature (frame->actual_method);
- if (!mono_get_seq_points (frame->domain, frame->actual_method))
+ if (!jit->has_var_info || !mono_get_seq_points (frame->domain, frame->actual_method))
/*
* The method is probably from an aot image compiled without soft-debug, variables might be dead, etc.
*/
g_free (val);
} else {
guint8 *field_value = NULL;
- void *field_storage = NULL;
if (remote_obj) {
#ifndef DISABLE_REMOTING
+ void *field_storage = NULL;
field_value = mono_load_remote_field_checked(obj, obj_type, f, &field_storage, &error);
if (!is_ok (&error)) {
mono_error_cleanup (&error); /* FIXME report the error */
{
const char *cpu_arch;
+#ifdef TARGET_WATCHOS
+ mini_get_debug_options ()->soft_breakpoints = TRUE;
+#endif
+
mono_os_mutex_init_recursive (&mini_arch_mutex);
if (mini_get_debug_options ()->soft_breakpoints) {
breakpoint_tramp = mini_get_breakpoint_trampoline ();
v6_supported = mono_hwcap_arm_is_v6;
v7_supported = mono_hwcap_arm_is_v7;
+ /*
+ * On weird devices, the hwcap code may fail to detect
+ * the ARM version. In that case, we can at least safely
+ * assume the version the runtime was compiled for.
+ */
+#ifdef HAVE_ARMV5
+ v5_supported = TRUE;
+#endif
+#ifdef HAVE_ARMV6
+ v6_supported = TRUE;
+#endif
+#ifdef HAVE_ARMV7
+ v7_supported = TRUE;
+#endif
+
#if defined(__APPLE__)
/* iOS is special-cased here because we don't yet
have a way to properly detect CPU features on it. */
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;
offset += size;
+ }
+ if (cfg->arch.ss_trigger_page_var) {
+ MonoInst *ins;
ins = cfg->arch.ss_trigger_page_var;
size = 4;
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;
offset += size;
+ }
+ if (cfg->arch.seq_point_bp_method_var) {
+ MonoInst *ins;
ins = cfg->arch.seq_point_bp_method_var;
size = 4;
}
if (cfg->gen_sdb_seq_points) {
+ if (cfg->compile_aot) {
+ MonoInst *ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ ins->flags |= MONO_INST_VOLATILE;
+ cfg->arch.seq_point_info_var = ins;
+
+ if (!cfg->soft_breakpoints) {
+ /* Allocate a separate variable for this to save 1 load per seq point */
+ ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ ins->flags |= MONO_INST_VOLATILE;
+ cfg->arch.ss_trigger_page_var = ins;
+ }
+ }
if (cfg->soft_breakpoints) {
MonoInst *ins;
ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
ins->flags |= MONO_INST_VOLATILE;
cfg->arch.seq_point_bp_method_var = ins;
-
- g_assert (!cfg->compile_aot);
- } else if (cfg->compile_aot) {
- MonoInst *ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
- ins->flags |= MONO_INST_VOLATILE;
- cfg->arch.seq_point_info_var = ins;
-
- /* Allocate a separate variable for this to save 1 load per seq point */
- ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
- ins->flags |= MONO_INST_VOLATILE;
- cfg->arch.ss_trigger_page_var = ins;
}
}
}
MonoInst *var;
int dreg = ARMREG_LR;
+#if 0
if (cfg->soft_breakpoints) {
g_assert (!cfg->compile_aot);
}
+#endif
/*
* For AOT, we use one got slot per method, which will point to a
mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
- if (cfg->soft_breakpoints) {
- /* Load the address of the breakpoint method into ip. */
- var = bp_method_var;
- g_assert (var);
- g_assert (var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (var->inst_offset));
- ARM_LDR_IMM (code, dreg, var->inst_basereg, var->inst_offset);
-
- /*
- * A placeholder for a possible breakpoint inserted by
- * mono_arch_set_breakpoint ().
- */
- ARM_NOP (code);
- } else if (cfg->compile_aot) {
+ if (cfg->compile_aot) {
guint32 offset = code - cfg->native_code;
guint32 val;
/* What is faster, a branch or a load ? */
ARM_CMP_REG_IMM (code, dreg, 0, 0);
/* The breakpoint instruction */
- ARM_LDR_IMM_COND (code, dreg, dreg, 0, ARMCOND_NE);
+ if (cfg->soft_breakpoints)
+ ARM_BLX_REG_COND (code, ARMCOND_NE, dreg);
+ else
+ ARM_LDR_IMM_COND (code, dreg, dreg, 0, ARMCOND_NE);
+ } else if (cfg->soft_breakpoints) {
+ /* Load the address of the breakpoint method into ip. */
+ var = bp_method_var;
+ g_assert (var);
+ g_assert (var->opcode == OP_REGOFFSET);
+ g_assert (arm_is_imm12 (var->inst_offset));
+ ARM_LDR_IMM (code, dreg, var->inst_basereg, var->inst_offset);
+
+ /*
+ * A placeholder for a possible breakpoint inserted by
+ * mono_arch_set_breakpoint ().
+ */
+ ARM_NOP (code);
} else {
/*
* A placeholder for a possible breakpoint inserted by
guint32 native_offset = ip - (guint8*)ji->code_start;
MonoDebugOptions *opt = mini_get_debug_options ();
- if (opt->soft_breakpoints) {
- g_assert (!ji->from_aot);
- code += 4;
- ARM_BLX_REG (code, ARMREG_LR);
- mono_arch_flush_icache (code - 4, 4);
- } else if (ji->from_aot) {
+ if (ji->from_aot) {
SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start);
g_assert (native_offset % 4 == 0);
g_assert (info->bp_addrs [native_offset / 4] == 0);
- info->bp_addrs [native_offset / 4] = bp_trigger_page;
+ info->bp_addrs [native_offset / 4] = opt->soft_breakpoints ? breakpoint_tramp : bp_trigger_page;
+ } else if (opt->soft_breakpoints) {
+ code += 4;
+ ARM_BLX_REG (code, ARMREG_LR);
+ mono_arch_flush_icache (code - 4, 4);
} else {
int dreg = ARMREG_LR;
guint8 *code = ip;
int i;
- if (opt->soft_breakpoints) {
- g_assert (!ji->from_aot);
- code += 4;
- ARM_NOP (code);
- mono_arch_flush_icache (code - 4, 4);
- } else if (ji->from_aot) {
+ if (ji->from_aot) {
guint32 native_offset = ip - (guint8*)ji->code_start;
SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start);
g_assert (native_offset % 4 == 0);
- g_assert (info->bp_addrs [native_offset / 4] == bp_trigger_page);
+ g_assert (info->bp_addrs [native_offset / 4] == (opt->soft_breakpoints ? breakpoint_tramp : bp_trigger_page));
info->bp_addrs [native_offset / 4] = 0;
+ } else if (opt->soft_breakpoints) {
+ code += 4;
+ ARM_NOP (code);
+ mono_arch_flush_icache (code - 4, 4);
} else {
for (i = 0; i < 4; ++i)
ARM_NOP (code);
mono_simd_intrinsics_init ();
#endif
-#if MONO_SUPPORT_TASKLETS
mono_tasklets_init ();
-#endif
register_trampolines (domain);
register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
-#ifndef DISABLE_REMOTING
- register_icall (mono_store_remote_field_new_icall, "mono_store_remote_field_new_icall", "void object ptr ptr object", FALSE);
-#endif
#if defined(__native_client__) || defined(__native_client_codegen__)
register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE);
if (code)
return code;
if (mono_llvm_only) {
- if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST ||
- method->wrapper_type == MONO_WRAPPER_STFLD_REMOTE)
+ if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST)
/* These wrappers are not generated */
return method_not_found;
/* Methods are lazily initialized on first call, so this can't lead recursion */
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 135
+#define MONO_AOT_FILE_VERSION 136
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
mono_tasklets_cleanup (void)
{
}
+#else
+static
+void continuations_not_supported (void)
+{
+ mono_set_pending_exception (mono_get_exception_not_implemented ("Tasklets are not implemented on this platform."));
+}
+
+static void*
+continuation_alloc (void)
+{
+ continuations_not_supported ();
+ return NULL;
+}
+
+static void
+continuation_free (MonoContinuation *cont)
+{
+ continuations_not_supported ();
+}
+
+static MonoException*
+continuation_mark_frame (MonoContinuation *cont)
+{
+ continuations_not_supported ();
+ return NULL;
+}
+
+static int
+continuation_store (MonoContinuation *cont, int state, MonoException **e)
+{
+ continuations_not_supported ();
+ return 0;
+}
+
+static MonoException*
+continuation_restore (MonoContinuation *cont, int state)
+{
+ continuations_not_supported ();
+ return NULL;
+}
+
+void
+mono_tasklets_init(void)
+{
+ mono_add_internal_call ("Mono.Tasklets.Continuation::alloc", continuation_alloc);
+ mono_add_internal_call ("Mono.Tasklets.Continuation::free", continuation_free);
+ mono_add_internal_call ("Mono.Tasklets.Continuation::mark", continuation_mark_frame);
+ mono_add_internal_call ("Mono.Tasklets.Continuation::store", continuation_store);
+ mono_add_internal_call ("Mono.Tasklets.Continuation::restore", continuation_restore);
+
+}
#endif
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
+/*
+ * Defines
+ *
+ * GCObject* copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue)
+ *
+ * which allocates new space for `obj`, copies it there, forwards `obj` to its new location,
+ * and enqueues the copy into `queue`.
+ *
+ * To be defined by the includer:
+ *
+ * COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION(vt, obj, objsize, has_refs)
+ *
+ * Allocates space for promoting object `obj`, with size `objsize`, and initizializes the
+ * vtable with `vt`. `has_refs` indicates whether the object contains references.
+ *
+ * collector_pin_object(obj, queue)
+ *
+ * Called when no space for `obj` could be allocated. It must pin `obj` and enqueue it into
+ * `queue` for scanning.
+ */
+
extern guint64 stat_copy_object_called_nursery;
extern guint64 stat_objects_copied_nursery;
return (GCObject *)destination;
}
+
+#undef COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION
+#undef collector_pin_object
*/
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
- if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
- if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \
- GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
- SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \
- binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
- if (!object_is_pinned (*(ptr))) \
- missing_remsets = TRUE; \
- } \
- } \
+ if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
+ if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \
+ GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
+ gboolean is_pinned = object_is_pinned (*(ptr)); \
+ SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets%s.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt), is_pinned ? ", but object is pinned" : ""); \
+ binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), is_pinned); \
+ if (!is_pinned) \
+ missing_remsets = TRUE; \
+ } \
+ } \
} while (0)
/*
* Assumes the world is stopped.
*/
void
-sgen_check_consistency (void)
+sgen_check_remset_consistency (void)
{
// Need to add more checks
SGEN_LOG (1, "Heap consistency check done.");
+ if (missing_remsets)
+ binary_protocol_flush_buffers (TRUE);
if (!binary_protocol_is_enabled ())
g_assert (!missing_remsets);
}
FIXME Flag missing remsets due to pinning as non fatal
*/
#undef HANDLE_PTR
-#define HANDLE_PTR(ptr,obj) do { \
- if (*(char**)ptr) { \
+#define HANDLE_PTR(ptr,obj) do { \
+ if (*(char**)ptr) { \
if (!is_valid_object_pointer (*(char**)ptr)) { \
- bad_pointer_spew ((char*)obj, (char**)ptr); \
- } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \
- if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr)) && (!allow_missing_pinned || !SGEN_OBJECT_IS_PINNED (*(ptr)))) \
- missing_remset_spew ((char*)obj, (char**)ptr); \
- } \
- } \
+ bad_pointer_spew ((char*)obj, (char**)ptr); \
+ } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \
+ if (!allow_missing_pinned && !SGEN_OBJECT_IS_PINNED (*(ptr)) && !sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) \
+ missing_remset_spew ((char*)obj, (char**)ptr); \
+ } \
+ } \
} while (0)
static void
/* LOCKING: requires that the GC lock is held */
static void
-finalize_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, volatile gboolean *suspend, SgenHashTable *hash_table)
+finalize_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, SgenHashTable *hash_table)
{
GCObject *object;
gpointer dummy G_GNUC_UNUSED;
SGEN_LOG (5, "Enqueuing object for finalization: %p (%s) (%d)", object, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (object)), sgen_hash_table_num_entries (hash_table));
}
- if (*suspend)
+ if (sgen_suspend_finalizers)
break;
} SGEN_HASH_TABLE_FOREACH_END;
}
* objects are still alive.
*/
void
-sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data, volatile gboolean *suspend)
+sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data)
{
LOCK_GC;
sgen_process_fin_stage_entries ();
- finalize_with_predicate (predicate, user_data, suspend, &minor_finalizable_hash);
- finalize_with_predicate (predicate, user_data, suspend, &major_finalizable_hash);
+ finalize_with_predicate (predicate, user_data, &minor_finalizable_hash);
+ finalize_with_predicate (predicate, user_data, &major_finalizable_hash);
UNLOCK_GC;
}
guint32 collect_before_allocs = 0;
/* If set, do a whole heap check before each collection */
static gboolean whole_heap_check_before_collection = FALSE;
-/* If set, do a heap consistency check before each minor collection */
-static gboolean consistency_check_at_minor_collection = FALSE;
+/* If set, do a remset consistency check at various opportunities */
+static gboolean remset_consistency_checks = FALSE;
/* If set, do a mod union consistency check before each finishing collection pause */
static gboolean mod_union_consistency_check = FALSE;
/* If set, check whether mark bits are consistent after major collections */
static SGEN_TV_DECLARE (time_major_conc_collection_start);
static SGEN_TV_DECLARE (time_major_conc_collection_end);
-static SGEN_TV_DECLARE (last_minor_collection_start_tv);
-static SGEN_TV_DECLARE (last_minor_collection_end_tv);
-
int gc_debug_level = 0;
FILE* gc_debug_file;
* ######################################################################
*/
-typedef SgenGrayQueue GrayQueue;
-
/* forward declarations */
static void scan_from_registered_roots (char *addr_start, char *addr_end, int root_type, ScanCopyContext ctx);
SgenMajorCollector major_collector;
SgenMinorCollector sgen_minor_collector;
-/* FIXME: get rid of this */
-static GrayQueue gray_queue;
static SgenRememberedSet remset;
-/* The gray queue to use from the main collection thread. */
-#define WORKERS_DISTRIBUTE_GRAY_QUEUE (&gray_queue)
-
/*
* The gray queue a worker job must use. If we're not parallel or
* concurrent, we use the main gray queue.
*/
static SgenGrayQueue*
-sgen_workers_get_job_gray_queue (WorkerData *worker_data)
-{
- return worker_data ? &worker_data->private_gray_queue : WORKERS_DISTRIBUTE_GRAY_QUEUE;
-}
-
-static void
-gray_queue_redirect (SgenGrayQueue *queue)
+sgen_workers_get_job_gray_queue (WorkerData *worker_data, SgenGrayQueue *default_gray_queue)
{
- gboolean wake = FALSE;
-
- for (;;) {
- GrayQueueSection *section = sgen_gray_object_dequeue_section (queue);
- if (!section)
- break;
- sgen_section_gray_queue_enqueue ((SgenSectionGrayQueue *)queue->alloc_prepare_data, section);
- wake = TRUE;
- }
-
- if (wake) {
- g_assert (concurrent_collection_in_progress);
- sgen_workers_ensure_awake ();
- }
+ if (worker_data)
+ return &worker_data->private_gray_queue;
+ SGEN_ASSERT (0, default_gray_queue, "Why don't we have a default gray queue when we're not running in a worker thread?");
+ return default_gray_queue;
}
static void
gray_queue_enable_redirect (SgenGrayQueue *queue)
{
- if (!concurrent_collection_in_progress)
- return;
+ SGEN_ASSERT (0, concurrent_collection_in_progress, "Where are we redirecting the gray queue to, without a concurrent collection?");
- sgen_gray_queue_set_alloc_prepare (queue, gray_queue_redirect, sgen_workers_get_distribute_section_gray_queue ());
- gray_queue_redirect (queue);
+ sgen_gray_queue_set_alloc_prepare (queue, sgen_workers_take_from_queue_and_awake);
+ sgen_workers_take_from_queue_and_awake (queue);
}
void
sgen_drain_gray_stack (ScanCopyContext ctx)
{
ScanObjectFunc scan_func = ctx.ops->scan_object;
- GrayQueue *queue = ctx.queue;
+ SgenGrayQueue *queue = ctx.queue;
if (ctx.ops->drain_gray_stack)
return ctx.ops->drain_gray_stack (queue);
* when we can't promote an object because we're out of memory.
*/
void
-sgen_pin_object (GCObject *object, GrayQueue *queue)
+sgen_pin_object (GCObject *object, SgenGrayQueue *queue)
{
SGEN_ASSERT (0, sgen_ptr_in_nursery (object), "We're only supposed to use this for pinning nursery objects when out of memory.");
typedef struct {
SgenThreadPoolJob job;
SgenObjectOperations *ops;
+ SgenGrayQueue *gc_thread_gray_queue;
} ScanJob;
+static ScanCopyContext
+scan_copy_context_for_scan_job (void *worker_data_untyped, ScanJob *job)
+{
+ WorkerData *worker_data = (WorkerData *)worker_data_untyped;
+
+ return CONTEXT_FROM_OBJECT_OPERATIONS (job->ops, sgen_workers_get_job_gray_queue (worker_data, job->gc_thread_gray_queue));
+}
+
static void
job_remembered_set_scan (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- WorkerData *worker_data = (WorkerData *)worker_data_untyped;
- ScanJob *job_data = (ScanJob*)job;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
- remset.scan_remsets (ctx);
+ remset.scan_remsets (scan_copy_context_for_scan_job (worker_data_untyped, (ScanJob*)job));
}
typedef struct {
- SgenThreadPoolJob job;
- SgenObjectOperations *ops;
+ ScanJob scan_job;
char *heap_start;
char *heap_end;
int root_type;
static void
job_scan_from_registered_roots (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- WorkerData *worker_data = (WorkerData *)worker_data_untyped;
ScanFromRegisteredRootsJob *job_data = (ScanFromRegisteredRootsJob*)job;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, &job_data->scan_job);
scan_from_registered_roots (job_data->heap_start, job_data->heap_end, job_data->root_type, ctx);
}
typedef struct {
- SgenThreadPoolJob job;
- SgenObjectOperations *ops;
+ ScanJob scan_job;
char *heap_start;
char *heap_end;
} ScanThreadDataJob;
static void
job_scan_thread_data (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- WorkerData *worker_data = (WorkerData *)worker_data_untyped;
ScanThreadDataJob *job_data = (ScanThreadDataJob*)job;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, &job_data->scan_job);
sgen_client_scan_thread_data (job_data->heap_start, job_data->heap_end, TRUE, ctx);
}
typedef struct {
- SgenThreadPoolJob job;
- SgenObjectOperations *ops;
+ ScanJob scan_job;
SgenPointerQueue *queue;
} ScanFinalizerEntriesJob;
static void
job_scan_finalizer_entries (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- WorkerData *worker_data = (WorkerData *)worker_data_untyped;
ScanFinalizerEntriesJob *job_data = (ScanFinalizerEntriesJob*)job;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, &job_data->scan_job);
scan_finalizer_entries (job_data->queue, ctx);
}
static void
job_scan_major_mod_union_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- WorkerData *worker_data = (WorkerData *)worker_data_untyped;
ScanJob *job_data = (ScanJob*)job;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, job_data);
g_assert (concurrent_collection_in_progress);
major_collector.scan_card_table (CARDTABLE_SCAN_MOD_UNION, ctx);
static void
job_scan_los_mod_union_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- WorkerData *worker_data = (WorkerData *)worker_data_untyped;
ScanJob *job_data = (ScanJob*)job;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, job_data);
g_assert (concurrent_collection_in_progress);
sgen_los_scan_card_table (CARDTABLE_SCAN_MOD_UNION, ctx);
static void
job_mod_union_preclean (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- WorkerData *worker_data = (WorkerData *)worker_data_untyped;
ScanJob *job_data = (ScanJob*)job;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (job_data->ops, sgen_workers_get_job_gray_queue (worker_data));
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, job_data);
g_assert (concurrent_collection_in_progress);
}
static void
-init_gray_queue (gboolean use_workers)
+init_gray_queue (SgenGrayQueue *gc_thread_gray_queue, gboolean use_workers)
{
if (use_workers)
sgen_workers_init_distribute_gray_queue ();
- sgen_gray_object_queue_init (&gray_queue, NULL);
+ sgen_gray_object_queue_init (gc_thread_gray_queue, NULL, TRUE);
}
static void
-enqueue_scan_from_roots_jobs (char *heap_start, char *heap_end, SgenObjectOperations *ops, gboolean enqueue)
+enqueue_scan_from_roots_jobs (SgenGrayQueue *gc_thread_gray_queue, char *heap_start, char *heap_end, SgenObjectOperations *ops, gboolean enqueue)
{
ScanFromRegisteredRootsJob *scrrj;
ScanThreadDataJob *stdj;
/* registered roots, this includes static fields */
scrrj = (ScanFromRegisteredRootsJob*)sgen_thread_pool_job_alloc ("scan from registered roots normal", job_scan_from_registered_roots, sizeof (ScanFromRegisteredRootsJob));
- scrrj->ops = ops;
+ scrrj->scan_job.ops = ops;
+ scrrj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
scrrj->heap_start = heap_start;
scrrj->heap_end = heap_end;
scrrj->root_type = ROOT_TYPE_NORMAL;
- sgen_workers_enqueue_job (&scrrj->job, enqueue);
+ sgen_workers_enqueue_job (&scrrj->scan_job.job, enqueue);
scrrj = (ScanFromRegisteredRootsJob*)sgen_thread_pool_job_alloc ("scan from registered roots wbarrier", job_scan_from_registered_roots, sizeof (ScanFromRegisteredRootsJob));
- scrrj->ops = ops;
+ scrrj->scan_job.ops = ops;
+ scrrj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
scrrj->heap_start = heap_start;
scrrj->heap_end = heap_end;
scrrj->root_type = ROOT_TYPE_WBARRIER;
- sgen_workers_enqueue_job (&scrrj->job, enqueue);
+ sgen_workers_enqueue_job (&scrrj->scan_job.job, enqueue);
/* Threads */
stdj = (ScanThreadDataJob*)sgen_thread_pool_job_alloc ("scan thread data", job_scan_thread_data, sizeof (ScanThreadDataJob));
- stdj->ops = ops;
+ stdj->scan_job.ops = ops;
+ stdj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
stdj->heap_start = heap_start;
stdj->heap_end = heap_end;
- sgen_workers_enqueue_job (&stdj->job, enqueue);
+ sgen_workers_enqueue_job (&stdj->scan_job.job, enqueue);
/* Scan the list of objects ready for finalization. */
sfej = (ScanFinalizerEntriesJob*)sgen_thread_pool_job_alloc ("scan finalizer entries", job_scan_finalizer_entries, sizeof (ScanFinalizerEntriesJob));
+ sfej->scan_job.ops = ops;
+ sfej->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
sfej->queue = &fin_ready_queue;
- sfej->ops = ops;
- sgen_workers_enqueue_job (&sfej->job, enqueue);
+ sgen_workers_enqueue_job (&sfej->scan_job.job, enqueue);
sfej = (ScanFinalizerEntriesJob*)sgen_thread_pool_job_alloc ("scan critical finalizer entries", job_scan_finalizer_entries, sizeof (ScanFinalizerEntriesJob));
+ sfej->scan_job.ops = ops;
+ sfej->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
sfej->queue = &critical_fin_queue;
- sfej->ops = ops;
- sgen_workers_enqueue_job (&sfej->job, enqueue);
+ sgen_workers_enqueue_job (&sfej->scan_job.job, enqueue);
}
/*
char *nursery_next;
mword fragment_total;
ScanJob *sj;
- SgenObjectOperations *object_ops = &sgen_minor_collector.serial_ops;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (object_ops, &gray_queue);
+ SgenGrayQueue gc_thread_gray_queue;
+ SgenObjectOperations *object_ops;
+ ScanCopyContext ctx;
TV_DECLARE (atv);
TV_DECLARE (btv);
+ SGEN_TV_DECLARE (last_minor_collection_start_tv);
+ SGEN_TV_DECLARE (last_minor_collection_end_tv);
if (disable_minor_collections)
return TRUE;
binary_protocol_collection_begin (gc_stats.minor_gc_count, GENERATION_NURSERY);
+ if (sgen_concurrent_collection_in_progress ())
+ object_ops = &sgen_minor_collector.serial_ops_with_concurrent_major;
+ else
+ object_ops = &sgen_minor_collector.serial_ops;
+
if (do_verify_nursery || do_dump_nursery_content)
sgen_debug_verify_nursery (do_dump_nursery_content);
sgen_memgov_minor_collection_start ();
- init_gray_queue (FALSE);
+ init_gray_queue (&gc_thread_gray_queue, FALSE);
+ ctx = CONTEXT_FROM_OBJECT_OPERATIONS (object_ops, &gc_thread_gray_queue);
gc_stats.minor_gc_count ++;
sgen_clear_nursery_fragments ();
sgen_check_whole_heap (finish_up_concurrent_mark);
}
- if (consistency_check_at_minor_collection)
- sgen_check_consistency ();
sgen_process_fin_stage_entries ();
pin_objects_in_nursery (FALSE, ctx);
sgen_pinning_trim_queue_to_section (nursery_section);
+ if (remset_consistency_checks)
+ sgen_check_remset_consistency ();
+
TV_GETTIME (atv);
time_minor_pinning += TV_ELAPSED (btv, atv);
SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), (long long)TV_ELAPSED (btv, atv));
sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan remset", job_remembered_set_scan, sizeof (ScanJob));
sj->ops = object_ops;
+ sj->gc_thread_gray_queue = &gc_thread_gray_queue;
sgen_workers_enqueue_job (&sj->job, FALSE);
/* we don't have complete write barrier yet, so we scan all the old generation sections */
TV_GETTIME (atv);
time_minor_scan_pinned += TV_ELAPSED (btv, atv);
- enqueue_scan_from_roots_jobs (sgen_get_nursery_start (), nursery_next, object_ops, FALSE);
+ enqueue_scan_from_roots_jobs (&gc_thread_gray_queue, sgen_get_nursery_start (), nursery_next, object_ops, FALSE);
TV_GETTIME (btv);
time_minor_scan_roots += TV_ELAPSED (atv, btv);
sgen_pinning_setup_section (nursery_section);
}
+ /*
+ * This is the latest point at which we can do this check, because
+ * sgen_build_nursery_fragments() unpins nursery objects again.
+ */
+ if (remset_consistency_checks)
+ sgen_check_remset_consistency ();
+
/* walk the pin_queue, build up the fragment list of free memory, unmark
* pinned objects as we go, memzero() the empty fragments so they are ready for the
* next allocations.
time_minor_fragment_creation += TV_ELAPSED (atv, btv);
SGEN_LOG (2, "Fragment creation: %lld usecs, %lu bytes available", (long long)TV_ELAPSED (atv, btv), (unsigned long)fragment_total);
- if (consistency_check_at_minor_collection)
+ if (remset_consistency_checks)
sgen_check_major_refs ();
major_collector.finish_nursery_collection ();
/* clear cemented hash */
sgen_cement_clear_below_threshold ();
- g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
+ sgen_gray_object_queue_dispose (&gc_thread_gray_queue);
remset.finish_minor_collection ();
} CopyOrMarkFromRootsMode;
static void
-major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMode mode, SgenObjectOperations *object_ops)
+major_copy_or_mark_from_roots (SgenGrayQueue *gc_thread_gray_queue, size_t *old_next_pin_slot, CopyOrMarkFromRootsMode mode, SgenObjectOperations *object_ops)
{
LOSObject *bigobj;
TV_DECLARE (atv);
*/
char *heap_start = NULL;
char *heap_end = (char*)-1;
- ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (object_ops, WORKERS_DISTRIBUTE_GRAY_QUEUE);
+ ScanCopyContext ctx = CONTEXT_FROM_OBJECT_OPERATIONS (object_ops, gc_thread_gray_queue);
gboolean concurrent = mode != COPY_OR_MARK_FROM_ROOTS_SERIAL;
SGEN_ASSERT (0, !!concurrent == !!concurrent_collection_in_progress, "We've been called with the wrong mode.");
sgen_nursery_alloc_prepare_for_major ();
}
- init_gray_queue (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT);
-
TV_GETTIME (atv);
/* Pinning depends on this */
}
sgen_los_pin_object (bigobj->data);
if (SGEN_OBJECT_HAS_REFERENCES (bigobj->data))
- GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data, sgen_obj_get_descriptor ((GCObject*)bigobj->data));
+ GRAY_OBJECT_ENQUEUE (gc_thread_gray_queue, bigobj->data, sgen_obj_get_descriptor ((GCObject*)bigobj->data));
sgen_pin_stats_register_object (bigobj->data, GENERATION_OLD);
SGEN_LOG (6, "Marked large object %p (%s) size: %lu from roots", bigobj->data,
sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (bigobj->data)),
if (check_nursery_objects_pinned && !sgen_minor_collector.is_split)
sgen_check_nursery_objects_pinned (mode != COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT);
- major_collector.pin_objects (WORKERS_DISTRIBUTE_GRAY_QUEUE);
+ major_collector.pin_objects (gc_thread_gray_queue);
if (old_next_pin_slot)
*old_next_pin_slot = sgen_get_pinned_count ();
+ /*
+ * We don't actually pin when starting a concurrent collection, so the remset
+ * consistency check won't work.
+ */
+ if (remset_consistency_checks && mode != COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT)
+ sgen_check_remset_consistency ();
+
TV_GETTIME (btv);
time_major_pinning += TV_ELAPSED (atv, btv);
SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), (long long)TV_ELAPSED (atv, btv));
sgen_client_collecting_major_3 (&fin_ready_queue, &critical_fin_queue);
- enqueue_scan_from_roots_jobs (heap_start, heap_end, object_ops, FALSE);
+ enqueue_scan_from_roots_jobs (gc_thread_gray_queue, heap_start, heap_end, object_ops, FALSE);
TV_GETTIME (btv);
time_major_scan_roots += TV_ELAPSED (atv, btv);
/* Mod union preclean job */
sj = (ScanJob*)sgen_thread_pool_job_alloc ("preclean mod union cardtable", job_mod_union_preclean, sizeof (ScanJob));
sj->ops = object_ops;
+ sj->gc_thread_gray_queue = NULL;
sgen_workers_start_all_workers (object_ops, &sj->job);
} else {
sgen_workers_start_all_workers (object_ops, NULL);
}
- gray_queue_enable_redirect (WORKERS_DISTRIBUTE_GRAY_QUEUE);
+ gray_queue_enable_redirect (gc_thread_gray_queue);
}
if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
/* Mod union card table */
sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan mod union cardtable", job_scan_major_mod_union_card_table, sizeof (ScanJob));
sj->ops = object_ops;
+ sj->gc_thread_gray_queue = gc_thread_gray_queue;
sgen_workers_enqueue_job (&sj->job, FALSE);
sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan LOS mod union cardtable", job_scan_los_mod_union_card_table, sizeof (ScanJob));
sj->ops = object_ops;
+ sj->gc_thread_gray_queue = gc_thread_gray_queue;
sgen_workers_enqueue_job (&sj->job, FALSE);
TV_GETTIME (atv);
}
sgen_pin_stats_report ();
-}
-static void
-major_finish_copy_or_mark (CopyOrMarkFromRootsMode mode)
-{
if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
sgen_finish_pinning ();
}
static void
-major_start_collection (const char *reason, gboolean concurrent, size_t *old_next_pin_slot)
+major_start_collection (SgenGrayQueue *gc_thread_gray_queue, const char *reason, gboolean concurrent, size_t *old_next_pin_slot)
{
SgenObjectOperations *object_ops;
current_collection_generation = GENERATION_OLD;
- g_assert (sgen_section_gray_queue_is_empty (sgen_workers_get_distribute_section_gray_queue ()));
+ sgen_workers_assert_gray_queue_is_empty ();
if (!concurrent)
sgen_cement_reset ();
if (major_collector.start_major_collection)
major_collector.start_major_collection ();
- major_copy_or_mark_from_roots (old_next_pin_slot, concurrent ? COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT : COPY_OR_MARK_FROM_ROOTS_SERIAL, object_ops);
- major_finish_copy_or_mark (concurrent ? COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT : COPY_OR_MARK_FROM_ROOTS_SERIAL);
+ major_copy_or_mark_from_roots (gc_thread_gray_queue, old_next_pin_slot, concurrent ? COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT : COPY_OR_MARK_FROM_ROOTS_SERIAL, object_ops);
}
static void
-major_finish_collection (const char *reason, gboolean is_overflow, size_t old_next_pin_slot, gboolean forced)
+major_finish_collection (SgenGrayQueue *gc_thread_gray_queue, const char *reason, gboolean is_overflow, size_t old_next_pin_slot, gboolean forced)
{
ScannedObjectCounts counts;
SgenObjectOperations *object_ops;
if (concurrent_collection_in_progress) {
object_ops = &major_collector.major_ops_concurrent_finish;
- major_copy_or_mark_from_roots (NULL, COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT, object_ops);
-
- major_finish_copy_or_mark (COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT);
+ major_copy_or_mark_from_roots (gc_thread_gray_queue, NULL, COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT, object_ops);
#ifdef SGEN_DEBUG_INTERNAL_ALLOC
main_gc_thread = NULL;
object_ops = &major_collector.major_ops_serial;
}
- g_assert (sgen_section_gray_queue_is_empty (sgen_workers_get_distribute_section_gray_queue ()));
+ sgen_workers_assert_gray_queue_is_empty ();
- /* all the objects in the heap */
- finish_gray_stack (GENERATION_OLD, CONTEXT_FROM_OBJECT_OPERATIONS (object_ops, &gray_queue));
+ finish_gray_stack (GENERATION_OLD, CONTEXT_FROM_OBJECT_OPERATIONS (object_ops, gc_thread_gray_queue));
TV_GETTIME (atv);
time_major_finish_gray_stack += TV_ELAPSED (btv, atv);
reset_heap_boundaries ();
sgen_update_heap_boundaries ((mword)sgen_get_nursery_start (), (mword)sgen_get_nursery_end ());
+ if (whole_heap_check_before_collection)
+ sgen_check_whole_heap (FALSE);
+
/* walk the pin_queue, build up the fragment list of free memory, unmark
* pinned objects as we go, memzero() the empty fragments so they are ready for the
* next allocations.
sgen_client_finalize_notify ();
}
- g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
-
sgen_memgov_major_collection_end (forced, concurrent_collection_in_progress, reason, is_overflow);
current_collection_generation = -1;
memset (&counts, 0, sizeof (ScannedObjectCounts));
major_collector.finish_major_collection (&counts);
- g_assert (sgen_section_gray_queue_is_empty (sgen_workers_get_distribute_section_gray_queue ()));
+ sgen_workers_assert_gray_queue_is_empty ();
SGEN_ASSERT (0, sgen_workers_all_done (), "Can't have workers working after major collection has finished");
if (concurrent_collection_in_progress)
TV_DECLARE (time_start);
TV_DECLARE (time_end);
size_t old_next_pin_slot;
+ SgenGrayQueue gc_thread_gray_queue;
if (disable_major_collections)
return FALSE;
/* world must be stopped already */
TV_GETTIME (time_start);
- major_start_collection (reason, FALSE, &old_next_pin_slot);
- major_finish_collection (reason, is_overflow, old_next_pin_slot, forced);
+ init_gray_queue (&gc_thread_gray_queue, FALSE);
+ major_start_collection (&gc_thread_gray_queue, reason, FALSE, &old_next_pin_slot);
+ major_finish_collection (&gc_thread_gray_queue, reason, is_overflow, old_next_pin_slot, forced);
+ sgen_gray_object_queue_dispose (&gc_thread_gray_queue);
TV_GETTIME (time_end);
gc_stats.major_gc_time += TV_ELAPSED (time_start, time_end);
TV_DECLARE (time_start);
TV_DECLARE (time_end);
long long num_objects_marked;
+ SgenGrayQueue gc_thread_gray_queue;
if (disable_major_collections)
return;
binary_protocol_concurrent_start ();
+ init_gray_queue (&gc_thread_gray_queue, TRUE);
// FIXME: store reason and pass it when finishing
- major_start_collection (reason, TRUE, NULL);
-
- gray_queue_redirect (&gray_queue);
+ major_start_collection (&gc_thread_gray_queue, reason, TRUE, NULL);
+ sgen_gray_object_queue_dispose (&gc_thread_gray_queue);
num_objects_marked = major_collector.get_and_reset_num_major_objects_marked ();
static gboolean
major_should_finish_concurrent_collection (void)
{
- SGEN_ASSERT (0, sgen_gray_object_queue_is_empty (&gray_queue), "Why is the gray queue not empty before we have started doing anything?");
return sgen_workers_all_done ();
}
static void
major_finish_concurrent_collection (gboolean forced)
{
+ SgenGrayQueue gc_thread_gray_queue;
TV_DECLARE (total_start);
TV_DECLARE (total_end);
current_collection_generation = GENERATION_OLD;
sgen_cement_reset ();
- major_finish_collection ("finishing", FALSE, -1, forced);
-
- if (whole_heap_check_before_collection)
- sgen_check_whole_heap (FALSE);
+ init_gray_queue (&gc_thread_gray_queue, FALSE);
+ major_finish_collection (&gc_thread_gray_queue, "finishing", FALSE, -1, forced);
+ sgen_gray_object_queue_dispose (&gc_thread_gray_queue);
TV_GETTIME (total_end);
- gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end) - TV_ELAPSED (last_minor_collection_start_tv, last_minor_collection_end_tv);
+ gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end);
current_collection_generation = -1;
}
degraded_mode = 1;
}
- g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
-
TV_GETTIME (gc_total_end);
time_max = MAX (time_max, TV_ELAPSED (gc_total_start, gc_total_end));
*/
static volatile gboolean pending_unqueued_finalizer = FALSE;
+volatile gboolean sgen_suspend_finalizers = FALSE;
+
+void
+sgen_set_suspend_finalizers (void)
+{
+ sgen_suspend_finalizers = TRUE;
+}
int
sgen_gc_invoke_finalizers (void)
gboolean
sgen_have_pending_finalizers (void)
{
+ if (sgen_suspend_finalizers)
+ return FALSE;
return pending_unqueued_finalizer || !sgen_pointer_queue_is_empty (&fin_ready_queue) || !sgen_pointer_queue_is_empty (&critical_fin_queue);
}
collect_before_allocs = atoi (arg);
} else if (!strcmp (opt, "verify-before-collections")) {
whole_heap_check_before_collection = TRUE;
- } else if (!strcmp (opt, "check-at-minor-collections")) {
- consistency_check_at_minor_collection = TRUE;
+ } else if (!strcmp (opt, "check-remset-consistency")) {
+ remset_consistency_checks = TRUE;
nursery_clear_policy = CLEAR_AT_GC;
} else if (!strcmp (opt, "mod-union-consistency-check")) {
if (!major_collector.is_concurrent) {
fprintf (stderr, "Valid <option>s are:\n");
fprintf (stderr, " collect-before-allocs[=<n>]\n");
fprintf (stderr, " verify-before-allocs[=<n>]\n");
- fprintf (stderr, " check-at-minor-collections\n");
+ fprintf (stderr, " check-remset-consistency\n");
fprintf (stderr, " check-mark-bits\n");
fprintf (stderr, " check-nursery-pinned\n");
fprintf (stderr, " verify-before-collections\n");
GCObject* (*alloc_for_promotion) (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references);
SgenObjectOperations serial_ops;
+ SgenObjectOperations serial_ops_with_concurrent_major;
void (*prepare_to_space) (char *to_space_bitmap, size_t space_bitmap_size);
void (*clear_fragments) (void);
gboolean sgen_have_pending_finalizers (void);
void sgen_object_register_for_finalization (GCObject *obj, void *user_data);
-void sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data, volatile gboolean *suspend);
+void sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data);
void sgen_remove_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, int generation);
+void sgen_set_suspend_finalizers (void);
void sgen_register_disappearing_link (GCObject *obj, void **link, gboolean track, gboolean in_gc);
extern gboolean sgen_try_free_some_memory;
extern mword total_promoted_size;
extern mword total_allocated_major;
-
+extern volatile gboolean sgen_suspend_finalizers;
extern MonoCoopMutex gc_mutex;
/* Nursery helpers. */
/* Debug support */
-void sgen_check_consistency (void);
+void sgen_check_remset_consistency (void);
void sgen_check_mod_union_consistency (void);
void sgen_check_major_refs (void);
void sgen_check_whole_heap (gboolean allow_missing_pinning);
#define STATE_ASSERT(s,v)
#endif
+/*
+ * Whenever we dispose a gray queue, we save its free list. Then, in the next collection,
+ * we reuse that free list for the new gray queue.
+ */
+static GrayQueueSection *last_gray_queue_free_list;
+
void
sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue)
{
}
void
-sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func)
+sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func, gboolean reuse_free_list)
{
- g_assert (sgen_gray_object_queue_is_empty (queue));
+ memset (queue, 0, sizeof (SgenGrayQueue));
- queue->alloc_prepare_func = NULL;
- queue->alloc_prepare_data = NULL;
#ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE
queue->enqueue_check_func = enqueue_check_func;
#endif
- /* Free the extra sections allocated during the last collection */
- sgen_gray_object_queue_trim_free_list (queue);
-}
-
-static void
-invalid_prepare_func (SgenGrayQueue *queue)
-{
- g_assert_not_reached ();
+ if (reuse_free_list) {
+ queue->free_list = last_gray_queue_free_list;
+ last_gray_queue_free_list = NULL;
+ }
}
void
-sgen_gray_object_queue_init_invalid (SgenGrayQueue *queue)
+sgen_gray_object_queue_dispose (SgenGrayQueue *queue)
{
- sgen_gray_object_queue_init (queue, NULL);
- queue->alloc_prepare_func = invalid_prepare_func;
- queue->alloc_prepare_data = NULL;
-}
+ SGEN_ASSERT (0, sgen_gray_object_queue_is_empty (queue), "Why are we disposing a gray queue that's not empty?");
-void
-sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func, void *data)
-{
- SGEN_ASSERT (0, !queue->alloc_prepare_func && !queue->alloc_prepare_data, "Can't set gray queue alloc-prepare twice");
- queue->alloc_prepare_func = alloc_prepare_func;
- queue->alloc_prepare_data = data;
+ /* Free the extra sections allocated during the last collection */
+ sgen_gray_object_queue_trim_free_list (queue);
+
+ SGEN_ASSERT (0, !last_gray_queue_free_list, "Are we disposing two gray queues after another?");
+ last_gray_queue_free_list = queue->free_list;
+
+ /* just to make sure */
+ memset (queue, 0, sizeof (SgenGrayQueue));
}
void
-sgen_gray_object_queue_init_with_alloc_prepare (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func,
- GrayQueueAllocPrepareFunc alloc_prepare_func, void *data)
+sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func)
{
- sgen_gray_object_queue_init (queue, enqueue_check_func);
- sgen_gray_queue_set_alloc_prepare (queue, alloc_prepare_func, data);
+ SGEN_ASSERT (0, !queue->alloc_prepare_func, "Can't set gray queue alloc-prepare twice");
+ queue->alloc_prepare_func = alloc_prepare_func;
}
void
}
}
-void
-sgen_gray_object_queue_disable_alloc_prepare (SgenGrayQueue *queue)
-{
- queue->alloc_prepare_func = NULL;
- queue->alloc_prepare_data = NULL;
-}
-
static void
lock_section_queue (SgenSectionGrayQueue *queue)
{
#ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE
GrayQueueEnqueueCheckFunc enqueue_check_func;
#endif
- void *alloc_prepare_data;
};
typedef struct _SgenSectionGrayQueue SgenSectionGrayQueue;
GrayQueueSection* sgen_gray_object_dequeue_section (SgenGrayQueue *queue);
void sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *section);
void sgen_gray_object_queue_trim_free_list (SgenGrayQueue *queue);
-void sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func);
-void sgen_gray_object_queue_init_invalid (SgenGrayQueue *queue);
-void sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func, void *data);
-void sgen_gray_object_queue_init_with_alloc_prepare (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func,
- GrayQueueAllocPrepareFunc func, void *data);
+void sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func, gboolean reuse_free_list);
+void sgen_gray_object_queue_dispose (SgenGrayQueue *queue);
+void sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func);
void sgen_gray_object_queue_deinit (SgenGrayQueue *queue);
-void sgen_gray_object_queue_disable_alloc_prepare (SgenGrayQueue *queue);
void sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue);
void sgen_gray_object_free_queue_section (GrayQueueSection *section);
{
LOSObject *obj;
- *start = NULL;
+ if (start)
+ *start = NULL;
for (obj = los_object_list; obj; obj = obj->next) {
char *end = (char*)obj->data + sgen_los_object_size (obj);
if (ptr >= (char*)obj->data && ptr < end) {
- *start = (char*)obj->data;
+ if (start)
+ *start = (char*)obj->data;
return TRUE;
}
}
}
static gboolean
-ptr_is_from_pinned_alloc (char *ptr)
+ptr_is_in_major_block (char *ptr, char **start, gboolean *pinned)
{
MSBlockInfo *block;
FOREACH_BLOCK_NO_LOCK (block) {
- if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE)
- return block->pinned;
+ if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) {
+ int count = MS_BLOCK_FREE / block->obj_size;
+ int i;
+
+ if (start)
+ *start = NULL;
+ for (i = 0; i <= count; ++i) {
+ if (ptr >= (char*)MS_BLOCK_OBJ (block, i) && ptr < (char*)MS_BLOCK_OBJ (block, i + 1)) {
+ if (start)
+ *start = (char *)MS_BLOCK_OBJ (block, i);
+ break;
+ }
+ }
+ if (pinned)
+ *pinned = block->pinned;
+ return TRUE;
+ }
} END_FOREACH_BLOCK_NO_LOCK;
return FALSE;
}
+static gboolean
+ptr_is_from_pinned_alloc (char *ptr)
+{
+ gboolean pinned;
+ if (ptr_is_in_major_block (ptr, NULL, &pinned))
+ return pinned;
+ return FALSE;
+}
+
static void
ensure_can_access_block_free_list (MSBlockInfo *block)
{
static gboolean
major_ptr_is_in_non_pinned_space (char *ptr, char **start)
{
- MSBlockInfo *block;
-
- FOREACH_BLOCK_NO_LOCK (block) {
- if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) {
- int count = MS_BLOCK_FREE / block->obj_size;
- int i;
-
- *start = NULL;
- for (i = 0; i <= count; ++i) {
- if (ptr >= (char*)MS_BLOCK_OBJ (block, i) && ptr < (char*)MS_BLOCK_OBJ (block, i + 1)) {
- *start = (char *)MS_BLOCK_OBJ (block, i);
- break;
- }
- }
- return !block->pinned;
- }
- } END_FOREACH_BLOCK_NO_LOCK;
+ gboolean pinned;
+ if (ptr_is_in_major_block (ptr, start, &pinned))
+ return !pinned;
return FALSE;
}
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
-#define collector_pin_object(obj, queue) sgen_pin_object (obj, queue);
-#define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION alloc_for_promotion
+#undef SERIAL_COPY_OBJECT
+#undef SERIAL_COPY_OBJECT_FROM_OBJ
-extern guint64 stat_nursery_copy_object_failed_to_space; /* from sgen-gc.c */
+#if defined(SGEN_SIMPLE_NURSERY)
+
+#ifdef SGEN_CONCURRENT_MAJOR
+#define SERIAL_COPY_OBJECT simple_nursery_serial_with_concurrent_major_copy_object
+#define SERIAL_COPY_OBJECT_FROM_OBJ simple_nursery_serial_with_concurrent_major_copy_object_from_obj
+#else
+#define SERIAL_COPY_OBJECT simple_nursery_serial_copy_object
+#define SERIAL_COPY_OBJECT_FROM_OBJ simple_nursery_serial_copy_object_from_obj
+#endif
+
+#elif defined (SGEN_SPLIT_NURSERY)
+
+#ifdef SGEN_CONCURRENT_MAJOR
+#define SERIAL_COPY_OBJECT split_nursery_serial_with_concurrent_major_copy_object
+#define SERIAL_COPY_OBJECT_FROM_OBJ split_nursery_serial_with_concurrent_major_copy_object_from_obj
+#else
+#define SERIAL_COPY_OBJECT split_nursery_serial_copy_object
+#define SERIAL_COPY_OBJECT_FROM_OBJ split_nursery_serial_copy_object_from_obj
+#endif
+
+#else
+#error "No nursery configuration specified"
+#endif
-#include "sgen-copy-object.h"
+
+extern guint64 stat_nursery_copy_object_failed_to_space; /* from sgen-gc.c */
/*
* This is how the copying happens from the nursery to the old generation.
SGEN_ASSERT (9, sgen_obj_get_descriptor (forwarded), "forwarded object %p has no gc descriptor", forwarded);
SGEN_LOG (9, " (already forwarded to %p)", forwarded);
HEAVY_STAT (++stat_nursery_copy_object_failed_forwarded);
+#ifdef SGEN_CONCURRENT_MAJOR
+ /* See comment on STORE_STORE_FENCE below. */
+ STORE_STORE_FENCE;
+#endif
SGEN_UPDATE_REFERENCE (obj_slot, forwarded);
#ifndef SGEN_SIMPLE_NURSERY
if (G_UNLIKELY (sgen_ptr_in_nursery (forwarded) && !sgen_ptr_in_nursery (obj_slot) && !SGEN_OBJECT_IS_CEMENTED (forwarded)))
HEAVY_STAT (++stat_objects_copied_nursery);
copy = copy_object_no_checks (obj, queue);
+#ifdef SGEN_CONCURRENT_MAJOR
+ /*
+ * If an object is evacuated to the major heap and a reference to it, from the major
+ * heap, updated, the concurrent major collector might follow that reference and
+ * scan the new major object. To make sure the object contents are seen by the
+ * major collector we need this write barrier, so that the reference is seen after
+ * the object.
+ */
+ STORE_STORE_FENCE;
+#endif
SGEN_UPDATE_REFERENCE (obj_slot, copy);
#ifndef SGEN_SIMPLE_NURSERY
if (G_UNLIKELY (sgen_ptr_in_nursery (copy) && !sgen_ptr_in_nursery (obj_slot) && !SGEN_OBJECT_IS_CEMENTED (copy)))
}
#endif
}
-
-#define FILL_MINOR_COLLECTOR_COPY_OBJECT(collector) do { \
- (collector)->serial_ops.copy_or_mark_object = SERIAL_COPY_OBJECT; \
- } while (0)
extern guint64 stat_scan_object_called_nursery;
+#undef SERIAL_SCAN_OBJECT
+#undef SERIAL_SCAN_VTYPE
+#undef SERIAL_SCAN_PTR_FIELD
+
#if defined(SGEN_SIMPLE_NURSERY)
+
+#ifdef SGEN_CONCURRENT_MAJOR
+#define SERIAL_SCAN_OBJECT simple_nursery_serial_with_concurrent_major_scan_object
+#define SERIAL_SCAN_VTYPE simple_nursery_serial_with_concurrent_major_scan_vtype
+#define SERIAL_SCAN_PTR_FIELD simple_nursery_serial_with_concurrent_major_scan_ptr_field
+#else
#define SERIAL_SCAN_OBJECT simple_nursery_serial_scan_object
#define SERIAL_SCAN_VTYPE simple_nursery_serial_scan_vtype
+#define SERIAL_SCAN_PTR_FIELD simple_nursery_serial_scan_ptr_field
+#endif
#elif defined (SGEN_SPLIT_NURSERY)
+
+#ifdef SGEN_CONCURRENT_MAJOR
+#define SERIAL_SCAN_OBJECT split_nursery_serial_with_concurrent_major_scan_object
+#define SERIAL_SCAN_VTYPE split_nursery_serial_with_concurrent_major_scan_vtype
+#define SERIAL_SCAN_PTR_FIELD split_nursery_serial_with_concurrent_major_scan_ptr_field
+#else
#define SERIAL_SCAN_OBJECT split_nursery_serial_scan_object
#define SERIAL_SCAN_VTYPE split_nursery_serial_scan_vtype
+#define SERIAL_SCAN_PTR_FIELD split_nursery_serial_scan_ptr_field
+#endif
#else
-#error "Please define GC_CONF_NAME"
+#error "No nursery configuration specified"
#endif
#undef HANDLE_PTR
HANDLE_PTR (ptr, NULL);
}
-#define FILL_MINOR_COLLECTOR_SCAN_OBJECT(collector) do { \
- (collector)->serial_ops.scan_object = SERIAL_SCAN_OBJECT; \
- (collector)->serial_ops.scan_vtype = SERIAL_SCAN_VTYPE; \
- (collector)->serial_ops.scan_ptr_field = SERIAL_SCAN_PTR_FIELD; \
+#define FILL_MINOR_COLLECTOR_SCAN_OBJECT(ops) do { \
+ (ops)->scan_object = SERIAL_SCAN_OBJECT; \
+ (ops)->scan_vtype = SERIAL_SCAN_VTYPE; \
+ (ops)->scan_ptr_field = SERIAL_SCAN_PTR_FIELD; \
} while (0)
*
* The protocol entries that do flush have `FLUSH()` in their definition.
*/
-void
+gboolean
binary_protocol_flush_buffers (gboolean force)
{
#ifdef HAVE_UNISTD_H
int num_buffers = 0, i;
+ BinaryProtocolBuffer *header;
BinaryProtocolBuffer *buf;
BinaryProtocolBuffer **bufs;
if (binary_protocol_file == -1)
- return;
+ return FALSE;
if (!force && !try_lock_exclusive ())
- return;
+ return FALSE;
- for (buf = binary_protocol_buffers; buf != NULL; buf = buf->next)
+ header = binary_protocol_buffers;
+ for (buf = header; buf != NULL; buf = buf->next)
++num_buffers;
bufs = (BinaryProtocolBuffer **)sgen_alloc_internal_dynamic (num_buffers * sizeof (BinaryProtocolBuffer*), INTERNAL_MEM_BINARY_PROTOCOL, TRUE);
- for (buf = binary_protocol_buffers, i = 0; buf != NULL; buf = buf->next, i++)
+ for (buf = header, i = 0; buf != NULL; buf = buf->next, i++)
bufs [i] = buf;
SGEN_ASSERT (0, i == num_buffers, "Binary protocol buffer count error");
+ /*
+ * This might be incorrect when forcing, but all bets are off in that case, anyway,
+ * because we're trying to figure out a bug in the debugger.
+ */
binary_protocol_buffers = NULL;
for (i = num_buffers - 1; i >= 0; --i) {
if (!force)
unlock_exclusive ();
+
+ return TRUE;
#endif
}
void binary_protocol_init (const char *filename, long long limit);
gboolean binary_protocol_is_enabled (void);
-void binary_protocol_flush_buffers (gboolean force);
+gboolean binary_protocol_flush_buffers (gboolean force);
#define BEGIN_PROTOCOL_ENTRY0(method) \
void method (void);
#include "mono/sgen/sgen-protocol.h"
#include "mono/sgen/sgen-layout-stats.h"
#include "mono/sgen/sgen-client.h"
+#include "mono/utils/mono-memory-model.h"
static inline GCObject*
alloc_for_promotion (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references)
/******************************************Copy/Scan functins ************************************************/
+#define collector_pin_object(obj, queue) sgen_pin_object (obj, queue);
+#define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION alloc_for_promotion
+
+#include "sgen-copy-object.h"
+
#define SGEN_SIMPLE_NURSERY
-#define SERIAL_COPY_OBJECT simple_nursery_serial_copy_object
-#define SERIAL_COPY_OBJECT_FROM_OBJ simple_nursery_serial_copy_object_from_obj
+#include "sgen-minor-copy-object.h"
+#include "sgen-minor-scan-object.h"
+
+static void
+fill_serial_ops (SgenObjectOperations *ops)
+{
+ ops->copy_or_mark_object = SERIAL_COPY_OBJECT;
+ FILL_MINOR_COLLECTOR_SCAN_OBJECT (ops);
+}
+
+#define SGEN_CONCURRENT_MAJOR
#include "sgen-minor-copy-object.h"
#include "sgen-minor-scan-object.h"
+static void
+fill_serial_with_concurrent_major_ops (SgenObjectOperations *ops)
+{
+ ops->copy_or_mark_object = SERIAL_COPY_OBJECT;
+ FILL_MINOR_COLLECTOR_SCAN_OBJECT (ops);
+}
+
void
sgen_simple_nursery_init (SgenMinorCollector *collector)
{
collector->build_fragments_finish = build_fragments_finish;
collector->init_nursery = init_nursery;
- FILL_MINOR_COLLECTOR_COPY_OBJECT (collector);
- FILL_MINOR_COLLECTOR_SCAN_OBJECT (collector);
+ fill_serial_ops (&collector->serial_ops);
+ fill_serial_with_concurrent_major_ops (&collector->serial_ops_with_concurrent_major);
}
/******************************************Copy/Scan functins ************************************************/
+#define collector_pin_object(obj, queue) sgen_pin_object (obj, queue);
+#define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION alloc_for_promotion
+
+#include "sgen-copy-object.h"
+
#define SGEN_SPLIT_NURSERY
-#define SERIAL_COPY_OBJECT split_nursery_serial_copy_object
-#define SERIAL_COPY_OBJECT_FROM_OBJ split_nursery_serial_copy_object_from_obj
+#include "sgen-minor-copy-object.h"
+#include "sgen-minor-scan-object.h"
+
+static void
+fill_serial_ops (SgenObjectOperations *ops)
+{
+ ops->copy_or_mark_object = SERIAL_COPY_OBJECT;
+ FILL_MINOR_COLLECTOR_SCAN_OBJECT (ops);
+}
+
+#define SGEN_CONCURRENT_MAJOR
#include "sgen-minor-copy-object.h"
#include "sgen-minor-scan-object.h"
+static void
+fill_serial_with_concurrent_major_ops (SgenObjectOperations *ops)
+{
+ ops->copy_or_mark_object = SERIAL_COPY_OBJECT;
+ FILL_MINOR_COLLECTOR_SCAN_OBJECT (ops);
+}
+
void
sgen_split_nursery_init (SgenMinorCollector *collector)
{
collector->handle_gc_param = handle_gc_param;
collector->print_gc_param_usage = print_gc_param_usage;
- FILL_MINOR_COLLECTOR_COPY_OBJECT (collector);
- FILL_MINOR_COLLECTOR_SCAN_OBJECT (collector);
+ fill_serial_ops (&collector->serial_ops);
+ fill_serial_with_concurrent_major_ops (&collector->serial_ops_with_concurrent_major);
}
return state == STATE_WORKING || state == STATE_WORK_ENQUEUED;
}
-void
+static void
sgen_workers_ensure_awake (void)
{
State old_state;
init_private_gray_queue (WorkerData *data)
{
sgen_gray_object_queue_init (&data->private_gray_queue,
- sgen_get_major_collector ()->is_concurrent ? concurrent_enqueue_check : NULL);
+ sgen_get_major_collector ()->is_concurrent ? concurrent_enqueue_check : NULL,
+ FALSE);
}
static void
return state_is_working_or_enqueued (workers_state);
}
-SgenSectionGrayQueue*
-sgen_workers_get_distribute_section_gray_queue (void)
+void
+sgen_workers_assert_gray_queue_is_empty (void)
{
- return &workers_distribute_gray_queue;
+ SGEN_ASSERT (0, sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue), "Why is the workers gray queue not empty?");
+}
+
+void
+sgen_workers_take_from_queue_and_awake (SgenGrayQueue *queue)
+{
+ gboolean wake = FALSE;
+
+ for (;;) {
+ GrayQueueSection *section = sgen_gray_object_dequeue_section (queue);
+ if (!section)
+ break;
+ sgen_section_gray_queue_enqueue (&workers_distribute_gray_queue, section);
+ wake = TRUE;
+ }
+
+ if (wake) {
+ SGEN_ASSERT (0, sgen_concurrent_collection_in_progress (), "Why is there work to take when there's no concurrent collection in progress?");
+ sgen_workers_ensure_awake ();
+ }
}
#endif
void sgen_workers_init (int num_workers);
void sgen_workers_stop_all_workers (void);
void sgen_workers_start_all_workers (SgenObjectOperations *object_ops, SgenThreadPoolJob *finish_job);
-void sgen_workers_ensure_awake (void);
void sgen_workers_init_distribute_gray_queue (void);
void sgen_workers_enqueue_job (SgenThreadPoolJob *job, gboolean enqueue);
void sgen_workers_wait_for_jobs_finished (void);
gboolean sgen_workers_have_idle_work (void);
gboolean sgen_workers_all_done (void);
gboolean sgen_workers_are_working (void);
-SgenSectionGrayQueue* sgen_workers_get_distribute_section_gray_queue (void);
+void sgen_workers_assert_gray_queue_is_empty (void);
+void sgen_workers_take_from_queue_and_awake (SgenGrayQueue *queue);
#endif
mono_cond_t c;
};
-static inline gint
+static inline void
mono_coop_mutex_init (MonoCoopMutex *mutex)
{
- return mono_os_mutex_init (&mutex->m);
+ mono_os_mutex_init (&mutex->m);
}
-static inline gint
+static inline void
mono_coop_mutex_init_recursive (MonoCoopMutex *mutex)
{
- return mono_os_mutex_init_recursive (&mutex->m);
+ mono_os_mutex_init_recursive (&mutex->m);
}
static inline gint
return mono_os_mutex_destroy (&mutex->m);
}
-static inline gint
+static inline void
mono_coop_mutex_lock (MonoCoopMutex *mutex)
{
- gint res;
-
/* Avoid thread state switch if lock is not contended */
if (mono_os_mutex_trylock (&mutex->m) == 0)
- return 0;
+ return;
MONO_ENTER_GC_SAFE;
- res = mono_os_mutex_lock (&mutex->m);
+ mono_os_mutex_lock (&mutex->m);
MONO_EXIT_GC_SAFE;
-
- return res;
}
static inline gint
return mono_os_mutex_trylock (&mutex->m);
}
-static inline gint
+static inline void
mono_coop_mutex_unlock (MonoCoopMutex *mutex)
{
- return mono_os_mutex_unlock (&mutex->m);
+ mono_os_mutex_unlock (&mutex->m);
}
-static inline gint
+static inline void
mono_coop_cond_init (MonoCoopCond *cond)
{
- return mono_os_cond_init (&cond->c);
+ mono_os_cond_init (&cond->c);
}
static inline gint
return mono_os_cond_destroy (&cond->c);
}
-static inline gint
+static inline void
mono_coop_cond_wait (MonoCoopCond *cond, MonoCoopMutex *mutex)
{
- gint res;
-
MONO_ENTER_GC_SAFE;
- res = mono_os_cond_wait (&cond->c, &mutex->m);
+ mono_os_cond_wait (&cond->c, &mutex->m);
MONO_EXIT_GC_SAFE;
-
- return res;
}
static inline gint
return res;
}
-static inline gint
+static inline void
mono_coop_cond_signal (MonoCoopCond *cond)
{
- return mono_os_cond_signal (&cond->c);
+ mono_os_cond_signal (&cond->c);
}
-static inline gint
+static inline void
mono_coop_cond_broadcast (MonoCoopCond *cond)
{
- return mono_os_cond_broadcast (&cond->c);
+ mono_os_cond_broadcast (&cond->c);
}
G_END_DECLS
MonoSemType s;
};
-static inline gint
+static inline void
mono_coop_sem_init (MonoCoopSem *sem, int value)
{
- return mono_os_sem_init (&sem->s, value);
+ mono_os_sem_init (&sem->s, value);
}
-static inline gint
+static inline void
mono_coop_sem_destroy (MonoCoopSem *sem)
{
- return mono_os_sem_destroy (&sem->s);
+ mono_os_sem_destroy (&sem->s);
}
static inline gint
return res;
}
-static inline gint
+static inline MonoSemTimedwaitRet
mono_coop_sem_timedwait (MonoCoopSem *sem, guint timeout_ms, MonoSemFlags flags)
{
- gint res;
+ MonoSemTimedwaitRet res;
MONO_ENTER_GC_SAFE;
return res;
}
-static inline gint
+static inline void
mono_coop_sem_post (MonoCoopSem *sem)
{
- return mono_os_sem_post (&sem->s);
+ mono_os_sem_post (&sem->s);
}
G_END_DECLS
if (file) {
while ((line = fgets (buf, 512, file))) {
- if (!strncmp (line, "Processor", 9)) {
+ if (!strncmp (line, "Processor", 9) ||
+ !strncmp (line, "model name", 10)) {
char *ver = strstr (line, "(v");
if (ver) {
typedef pthread_mutex_t mono_mutex_t;
typedef pthread_cond_t mono_cond_t;
-static inline int
+static inline void
mono_os_mutex_init (mono_mutex_t *mutex)
{
- return pthread_mutex_init (mutex, NULL);
+ int res;
+
+ res = pthread_mutex_init (mutex, NULL);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_mutex_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
-static inline int
+static inline void
mono_os_mutex_init_recursive (mono_mutex_t *mutex)
{
int res;
pthread_mutexattr_t attr;
- pthread_mutexattr_init (&attr);
- pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+ res = pthread_mutexattr_init (&attr);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_mutexattr_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
+ res = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_mutexattr_settype failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
res = pthread_mutex_init (mutex, &attr);
- pthread_mutexattr_destroy (&attr);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_mutex_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
- return res;
+ res = pthread_mutexattr_destroy (&attr);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_mutexattr_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
static inline int
mono_os_mutex_destroy (mono_mutex_t *mutex)
{
- return pthread_mutex_destroy (mutex);
+ int res;
+
+ res = pthread_mutex_destroy (mutex);
+ if (G_UNLIKELY (res != 0 && res != EBUSY))
+ g_error ("%s: pthread_mutex_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
+ return res != 0 ? -1 : 0;
}
-static inline int
+static inline void
mono_os_mutex_lock (mono_mutex_t *mutex)
{
int res;
res = pthread_mutex_lock (mutex);
- g_assert (res != EINVAL);
-
- return res;
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_mutex_lock failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
static inline int
mono_os_mutex_trylock (mono_mutex_t *mutex)
{
- return pthread_mutex_trylock (mutex);
+ int res;
+
+ res = pthread_mutex_trylock (mutex);
+ if (G_UNLIKELY (res != 0 && res != EBUSY))
+ g_error ("%s: pthread_mutex_trylock failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
+ return res != 0 ? -1 : 0;
}
-static inline int
+static inline void
mono_os_mutex_unlock (mono_mutex_t *mutex)
{
- return pthread_mutex_unlock (mutex);
+ int res;
+
+ res = pthread_mutex_unlock (mutex);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_mutex_unlock failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
-static inline int
+static inline void
mono_os_cond_init (mono_cond_t *cond)
{
- return pthread_cond_init (cond, NULL);
+ int res;
+
+ res = pthread_cond_init (cond, NULL);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_cond_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
static inline int
mono_os_cond_destroy (mono_cond_t *cond)
{
- return pthread_cond_destroy (cond);
+ int res;
+
+ res = pthread_cond_destroy (cond);
+ if (G_UNLIKELY (res != 0 && res != EBUSY))
+ g_error ("%s: pthread_cond_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
+
+ return res != 0 ? -1 : 0;
}
-static inline int
+static inline void
mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex)
{
int res;
res = pthread_cond_wait (cond, mutex);
- g_assert (res != EINVAL);
-
- return res;
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_cond_wait failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
static inline int
gint64 usecs;
int res;
- if (timeout_ms == MONO_INFINITE_WAIT)
- return mono_os_cond_wait (cond, mutex);
+ if (timeout_ms == MONO_INFINITE_WAIT) {
+ mono_os_cond_wait (cond, mutex);
+ return 0;
+ }
/* ms = 10^-3, us = 10^-6, ns = 10^-9 */
- gettimeofday (&tv, NULL);
+ res = gettimeofday (&tv, NULL);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
+
tv.tv_sec += timeout_ms / 1000;
usecs = tv.tv_usec + ((timeout_ms % 1000) * 1000);
if (usecs >= 1000000) {
ts.tv_nsec = usecs * 1000;
res = pthread_cond_timedwait (cond, mutex, &ts);
- g_assert (res != EINVAL);
+ if (G_UNLIKELY (res != 0 && res != ETIMEDOUT))
+ g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d)", __func__, g_strerror (res), res);
- return res;
+ return res != 0 ? -1 : 0;
}
-static inline int
+static inline void
mono_os_cond_signal (mono_cond_t *cond)
{
- return pthread_cond_signal (cond);
+ int res;
+
+ res = pthread_cond_signal (cond);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_cond_signal failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
-static inline int
+static inline void
mono_os_cond_broadcast (mono_cond_t *cond)
{
- return pthread_cond_broadcast (cond);
+ int res;
+
+ res = pthread_cond_broadcast (cond);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: pthread_cond_broadcast failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
#else
typedef CRITICAL_SECTION mono_mutex_t;
typedef CONDITION_VARIABLE mono_cond_t;
-static inline int
+static inline void
mono_os_mutex_init (mono_mutex_t *mutex)
{
- InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
- return 0;
+ BOOL res;
+
+ res = InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
+ if (G_UNLIKELY (res == 0))
+ g_error ("%s: InitializeCriticalSectionEx failed with error %d", __func__, GetLastError ());
}
-static inline int
+static inline void
mono_os_mutex_init_recursive (mono_mutex_t *mutex)
{
- InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
- return 0;
+ BOOL res;
+
+ res = InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
+ if (G_UNLIKELY (res == 0))
+ g_error ("%s: InitializeCriticalSectionEx failed with error %d", __func__, GetLastError ());
}
static inline int
return 0;
}
-static inline int
+static inline void
mono_os_mutex_lock (mono_mutex_t *mutex)
{
EnterCriticalSection (mutex);
- return 0;
}
static inline int
mono_os_mutex_trylock (mono_mutex_t *mutex)
{
- return TryEnterCriticalSection (mutex) != 0 ? 0 : 1;
+ return TryEnterCriticalSection (mutex) == 0 ? -1 : 0;
}
-static inline int
+static inline void
mono_os_mutex_unlock (mono_mutex_t *mutex)
{
LeaveCriticalSection (mutex);
- return 0;
}
-static inline int
+static inline void
mono_os_cond_init (mono_cond_t *cond)
{
InitializeConditionVariable (cond);
- return 0;
}
static inline int
return 0;
}
-static inline int
+static inline void
mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex)
{
- return SleepConditionVariableCS (cond, mutex, INFINITE) ? 0 : 1;
+ BOOL res;
+
+ res = SleepConditionVariableCS (cond, mutex, INFINITE);
+ if (G_UNLIKELY (res == 0))
+ g_error ("%s: SleepConditionVariableCS failed with error %d", __func__, GetLastError ());
}
static inline int
mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
{
- return SleepConditionVariableCS (cond, mutex, timeout_ms) ? 0 : 1;
+ BOOL res;
+
+ res = SleepConditionVariableCS (cond, mutex, timeout_ms);
+ if (G_UNLIKELY (res == 0 && GetLastError () != ERROR_TIMEOUT))
+ g_error ("%s: SleepConditionVariableCS failed with error %d", __func__, GetLastError ());
+
+ return res == 0 ? -1 : 0;
}
-static inline int
+static inline void
mono_os_cond_signal (mono_cond_t *cond)
{
WakeConditionVariable (cond);
- return 0;
}
-static inline int
+static inline void
mono_os_cond_broadcast (mono_cond_t *cond)
{
WakeAllConditionVariable (cond);
- return 0;
}
#endif
MONO_SEM_FLAGS_ALERTABLE = 1 << 0,
} MonoSemFlags;
+typedef enum {
+ MONO_SEM_TIMEDWAIT_RET_SUCCESS = 0,
+ MONO_SEM_TIMEDWAIT_RET_ALERTED = -1,
+ MONO_SEM_TIMEDWAIT_RET_TIMEDOUT = -2,
+} MonoSemTimedwaitRet;
+
#if defined(USE_MACH_SEMA)
typedef semaphore_t MonoSemType;
-static inline int
+static inline void
mono_os_sem_init (MonoSemType *sem, int value)
{
- return semaphore_create (current_task (), sem, SYNC_POLICY_FIFO, value) != KERN_SUCCESS ? -1 : 0;
+ kern_return_t res;
+
+ res = semaphore_create (current_task (), sem, SYNC_POLICY_FIFO, value);
+ if (G_UNLIKELY (res != KERN_SUCCESS))
+ g_error ("%s: semaphore_create failed with error %d", __func__, res);
}
-static inline int
+static inline void
mono_os_sem_destroy (MonoSemType *sem)
{
- return semaphore_destroy (current_task (), *sem) != KERN_SUCCESS ? -1 : 0;
+ kern_return_t res;
+
+ res = semaphore_destroy (current_task (), *sem);
+ if (G_UNLIKELY (res != KERN_SUCCESS))
+ g_error ("%s: semaphore_destroy failed with error %d", __func__, res);
}
static inline int
mono_os_sem_wait (MonoSemType *sem, MonoSemFlags flags)
{
- int res;
+ kern_return_t res;
retry:
res = semaphore_wait (*sem);
- g_assert (res != KERN_INVALID_ARGUMENT);
+ if (G_UNLIKELY (res != KERN_SUCCESS && res != KERN_ABORTED))
+ g_error ("%s: semaphore_wait failed with error %d", __func__, res);
if (res == KERN_ABORTED && !(flags & MONO_SEM_FLAGS_ALERTABLE))
goto retry;
return res != KERN_SUCCESS ? -1 : 0;
}
-static inline int
+static inline MonoSemTimedwaitRet
mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags)
{
+ kern_return_t res;
+ int resint;
mach_timespec_t ts, copy;
struct timeval start, current;
- int res = 0;
if (timeout_ms == MONO_INFINITE_WAIT)
- return mono_os_sem_wait (sem, flags);
+ return (MonoSemTimedwaitRet) mono_os_sem_wait (sem, flags);
ts.tv_sec = timeout_ms / 1000;
ts.tv_nsec = (timeout_ms % 1000) * 1000000;
}
copy = ts;
- gettimeofday (&start, NULL);
+ resint = gettimeofday (&start, NULL);
+ if (G_UNLIKELY (resint != 0))
+ g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
retry:
res = semaphore_timedwait (*sem, ts);
- g_assert (res != KERN_INVALID_ARGUMENT);
+ if (G_UNLIKELY (res != KERN_SUCCESS && res != KERN_ABORTED && res != KERN_OPERATION_TIMED_OUT))
+ g_error ("%s: semaphore_timedwait failed with error %d", __func__, res);
if (res == KERN_ABORTED && !(flags & MONO_SEM_FLAGS_ALERTABLE)) {
ts = copy;
- gettimeofday (¤t, NULL);
+ resint = gettimeofday (¤t, NULL);
+ if (G_UNLIKELY (resint != 0))
+ g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
+
ts.tv_sec -= (current.tv_sec - start.tv_sec);
ts.tv_nsec -= (current.tv_usec - start.tv_usec) * 1000;
if (ts.tv_nsec < 0) {
goto retry;
}
- return res != KERN_SUCCESS ? -1 : 0;
+ switch (res) {
+ case KERN_SUCCESS:
+ return MONO_SEM_TIMEDWAIT_RET_SUCCESS;
+ case KERN_ABORTED:
+ return MONO_SEM_TIMEDWAIT_RET_ALERTED;
+ case KERN_OPERATION_TIMED_OUT:
+ return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT;
+ default:
+ g_assert_not_reached ();
+ }
}
-static inline int
+static inline void
mono_os_sem_post (MonoSemType *sem)
{
- int res;
+ kern_return_t res;
+
retry:
res = semaphore_signal (*sem);
- g_assert (res != KERN_INVALID_ARGUMENT);
+ if (G_UNLIKELY (res != KERN_SUCCESS && res != KERN_ABORTED))
+ g_error ("%s: semaphore_signal failed with error %d", __func__, res);
if (res == KERN_ABORTED)
goto retry;
-
- return res != KERN_SUCCESS ? -1 : 0;
}
#elif !defined(HOST_WIN32) && defined(HAVE_SEMAPHORE_H)
typedef sem_t MonoSemType;
-static inline int
+static inline void
mono_os_sem_init (MonoSemType *sem, int value)
{
- return sem_init (sem, 0, value);
+ int res;
+
+ res = sem_init (sem, 0, value);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: sem_init failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
}
-static inline int
+static inline void
mono_os_sem_destroy (MonoSemType *sem)
{
- return sem_destroy (sem);
+ int res;
+
+ res = sem_destroy (sem);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: sem_destroy failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
}
static inline int
retry:
res = sem_wait (sem);
- if (res == -1)
- g_assert (errno != EINVAL);
+ if (G_UNLIKELY (res != 0 && errno != EINTR))
+ g_error ("%s: sem_wait failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
- if (res == -1 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE))
+ if (res != 0 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE))
goto retry;
return res != 0 ? -1 : 0;
}
-static inline int
+static inline MonoSemTimedwaitRet
mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags)
{
struct timespec ts, copy;
struct timeval t;
- int res = 0;
+ int res;
if (timeout_ms == 0) {
- res = sem_trywait (sem) != 0 ? -1 : 0;
- if (res == -1)
- g_assert (errno != EINVAL);
-
- return res != 0 ? -1 : 0;
+ res = sem_trywait (sem);
+ if (G_UNLIKELY (res != 0 && errno != EINTR && errno != EAGAIN))
+ g_error ("%s: sem_trywait failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
+
+ if (res == 0)
+ return MONO_SEM_TIMEDWAIT_RET_SUCCESS;
+ else if (errno == EINTR)
+ return MONO_SEM_TIMEDWAIT_RET_ALERTED;
+ else if (errno == EAGAIN)
+ return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT;
+ else
+ g_assert_not_reached ();
}
if (timeout_ms == MONO_INFINITE_WAIT)
- return mono_os_sem_wait (sem, flags);
+ return (MonoSemTimedwaitRet) mono_os_sem_wait (sem, flags);
+
+ res = gettimeofday (&t, NULL);
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
- gettimeofday (&t, NULL);
ts.tv_sec = timeout_ms / 1000 + t.tv_sec;
ts.tv_nsec = (timeout_ms % 1000) * 1000000 + t.tv_usec * 1000;
while (ts.tv_nsec >= NSEC_PER_SEC) {
copy = ts;
retry:
-#if defined(__native_client__) && defined(USE_NEWLIB)
- res = sem_trywait (sem);
-#else
res = sem_timedwait (sem, &ts);
-#endif
- if (res == -1)
- g_assert (errno != EINVAL);
+ if (G_UNLIKELY (res != 0 && errno != EINTR && errno != ETIMEDOUT))
+ g_error ("%s: sem_timedwait failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
- if (res == -1 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE)) {
+ if (res != 0 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE)) {
ts = copy;
goto retry;
}
- return res != 0 ? -1 : 0;
+ if (res == 0)
+ return MONO_SEM_TIMEDWAIT_RET_SUCCESS;
+ else if (errno == EINTR)
+ return MONO_SEM_TIMEDWAIT_RET_ALERTED;
+ else if (errno == ETIMEDOUT)
+ return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT;
+ else
+ g_assert_not_reached ();
}
-static inline int
+static inline void
mono_os_sem_post (MonoSemType *sem)
{
int res;
res = sem_post (sem);
- if (res == -1)
- g_assert (errno != EINVAL);
-
- return res;
+ if (G_UNLIKELY (res != 0))
+ g_error ("%s: sem_post failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
}
#else
typedef HANDLE MonoSemType;
-static inline int
+static inline void
mono_os_sem_init (MonoSemType *sem, int value)
{
*sem = CreateSemaphore (NULL, value, 0x7FFFFFFF, NULL);
- return *sem == NULL ? -1 : 0;
+ if (G_UNLIKELY (*sem == NULL))
+ g_error ("%s: CreateSemaphore failed with error %d", __func__, GetLastError ());
}
-static inline int
+static inline void
mono_os_sem_destroy (MonoSemType *sem)
{
- return !CloseHandle (*sem) ? -1 : 0;
+ BOOL res;
+
+ res = CloseHandle (*sem);
+ if (G_UNLIKELY (res == 0))
+ g_error ("%s: CloseHandle failed with error %d", __func__, GetLastError ());
}
-static inline int
+static inline MonoSemTimedwaitRet
mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags)
{
- gboolean res;
+ BOOL res;
retry:
res = WaitForSingleObjectEx (*sem, timeout_ms, flags & MONO_SEM_FLAGS_ALERTABLE);
+ if (G_UNLIKELY (res != WAIT_OBJECT_0 && res != WAIT_IO_COMPLETION && res != WAIT_TIMEOUT))
+ g_error ("%s: WaitForSingleObjectEx failed with error %d", __func__, GetLastError ());
if (res == WAIT_IO_COMPLETION && !(flags & MONO_SEM_FLAGS_ALERTABLE))
goto retry;
- return res != WAIT_OBJECT_0 ? -1 : 0;
+ switch (res) {
+ case WAIT_OBJECT_0:
+ return MONO_SEM_TIMEDWAIT_RET_SUCCESS;
+ case WAIT_IO_COMPLETION:
+ return MONO_SEM_TIMEDWAIT_RET_ALERTED;
+ case WAIT_TIMEOUT:
+ return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT;
+ default:
+ g_assert_not_reached ();
+ }
}
static inline int
mono_os_sem_wait (MonoSemType *sem, MonoSemFlags flags)
{
- return mono_os_sem_timedwait (sem, INFINITE, flags);
+ return mono_os_sem_timedwait (sem, INFINITE, flags) != 0 ? -1 : 0;
}
-static inline int
+static inline void
mono_os_sem_post (MonoSemType *sem)
{
- return !ReleaseSemaphore (*sem, 1, NULL) ? -1 : 0;
+ BOOL res;
+
+ res = ReleaseSemaphore (*sem, 1, NULL);
+ if (G_UNLIKELY (res == 0))
+ g_error ("%s: ReleaseSemaphore failed with error %d", __func__, GetLastError ());
}
#endif
/* Register the thread with the io-layer */
handle = wapi_create_thread_handle ();
if (!handle) {
- res = mono_coop_sem_post (&(start_info->registered));
- g_assert (!res);
+ mono_coop_sem_post (&(start_info->registered));
return NULL;
}
start_info->handle = handle;
}
/* start_info is not valid after this */
- res = mono_coop_sem_post (&(start_info->registered));
- g_assert (!res);
+ mono_coop_sem_post (&(start_info->registered));
start_info = NULL;
if (flags & CREATE_SUSPENDED) {
info->runtime_thread = TRUE;
info->create_suspended = suspend;
- post_result = mono_coop_sem_post (&(start_info->registered));
- g_assert (!post_result);
+ mono_coop_sem_post (&(start_info->registered));
if (suspend) {
WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */
for (i = 0; i < pending_suspends; ++i) {
THREADS_SUSPEND_DEBUG ("[INITIATOR-WAIT-WAITING]\n");
InterlockedIncrement (&waits_done);
- if (!mono_os_sem_timedwait (&suspend_semaphore, sleepAbortDuration, MONO_SEM_FLAGS_NONE))
+ if (mono_os_sem_timedwait (&suspend_semaphore, sleepAbortDuration, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_SUCCESS)
continue;
mono_stopwatch_stop (&suspension_time);
mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast)
{
MonoW32HandleBase *handle_data;
- int thr_ret;
if (!mono_w32handle_lookup_data (handle, &handle_data)) {
return;
/* The condition the global signal cond is waiting on is the signalling of
* _any_ handle. So lock it before setting the signalled state.
*/
- thr_ret = mono_os_mutex_lock (&global_signal_mutex);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_mutex_lock result %d for global signal mutex", thr_ret);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&global_signal_mutex);
/* This function _must_ be called with
* handle->signal_mutex locked
handle_data->signalled=state;
if (broadcast == TRUE) {
- thr_ret = mono_os_cond_broadcast (&handle_data->signal_cond);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
- g_assert (thr_ret == 0);
+ mono_os_cond_broadcast (&handle_data->signal_cond);
} else {
- thr_ret = mono_os_cond_signal (&handle_data->signal_cond);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_cond_signal result %d for handle %p", thr_ret, handle);
- g_assert (thr_ret == 0);
+ mono_os_cond_signal (&handle_data->signal_cond);
}
/* Tell everyone blocking on multiple handles that something
* was signalled
*/
- thr_ret = mono_os_cond_broadcast (&global_signal_cond);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
- g_assert (thr_ret == 0);
+ mono_os_cond_broadcast (&global_signal_cond);
- thr_ret = mono_os_mutex_unlock (&global_signal_mutex);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_mutex_unlock result %d for global signal mutex", thr_ret);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&global_signal_mutex);
} else {
handle_data->signalled=state;
}
g_message ("%s: lock global signal mutex", __func__);
#endif
- return(mono_os_mutex_lock (&global_signal_mutex));
+ mono_os_mutex_lock (&global_signal_mutex);
+
+ return 0;
}
int
g_message ("%s: unlock global signal mutex", __func__);
#endif
- return(mono_os_mutex_unlock (&global_signal_mutex));
+ mono_os_mutex_unlock (&global_signal_mutex);
+
+ return 0;
}
int
mono_w32handle_ref (handle);
- return(mono_os_mutex_lock (&handle_data->signal_mutex));
+ mono_os_mutex_lock (&handle_data->signal_mutex);
+
+ return 0;
}
int
mono_w32handle_unlock_handle (gpointer handle)
{
MonoW32HandleBase *handle_data;
- int ret;
#ifdef DEBUG
g_message ("%s: unlocking handle %p", __func__, handle);
return(0);
}
- ret = mono_os_mutex_unlock (&handle_data->signal_mutex);
+ mono_os_mutex_unlock (&handle_data->signal_mutex);
mono_w32handle_unref (handle);
- return(ret);
+ return 0;
}
/*
static void mono_w32handle_init_handle (MonoW32HandleBase *handle,
MonoW32HandleType type, gpointer handle_specific)
{
- int thr_ret;
-
g_assert (!shutting_down);
handle->type = type;
handle->signalled = FALSE;
handle->ref = 1;
- thr_ret = mono_os_cond_init (&handle->signal_cond);
- g_assert (thr_ret == 0);
-
- thr_ret = mono_os_mutex_init (&handle->signal_mutex);
- g_assert (thr_ret == 0);
+ mono_os_cond_init (&handle->signal_cond);
+ mono_os_mutex_init (&handle->signal_mutex);
if (handle_specific)
handle->specific = g_memdup (handle_specific, mono_w32handle_ops_typesize (type));
{
guint32 handle_idx = 0;
gpointer handle;
- int thr_ret;
g_assert (!shutting_down);
g_assert(!type_is_fd(type));
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&scan_mutex);
while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == 0) {
/* Try and expand the array, and have another go */
private_handles_slots_count ++;
}
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&scan_mutex);
if (handle_idx == 0) {
/* We ran out of slots */
{
MonoW32HandleBase *handle_data;
int fd_index, fd_offset;
- int thr_ret;
g_assert (!shutting_down);
/* Initialize the array entries on demand */
if (!private_handles [fd_index]) {
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&scan_mutex);
if (!private_handles [fd_index])
private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&scan_mutex);
}
handle_data = &private_handles [fd_index][fd_offset];
MonoW32HandleBase *handle_data = NULL;
gpointer handle;
guint32 i, k;
- int thr_ret;
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&scan_mutex);
for (i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
if (private_handles [i]) {
}
done:
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&scan_mutex);
}
/* This might list some shared handles twice if they are already
gpointer ret = NULL;
guint32 i, k;
gboolean found = FALSE;
- int thr_ret;
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&scan_mutex);
for (i = SLOT_INDEX (0); !found && i < private_handles_slots_count; i++) {
if (private_handles [i]) {
}
}
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&scan_mutex);
if (!found) {
ret = NULL;
type = handle_data->type;
handle_specific = handle_data->specific;
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&scan_mutex);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Destroying handle %p", __func__, handle);
memset (handle_data, 0, sizeof (MonoW32HandleBase));
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&scan_mutex);
if (early_exit)
return;
{
MonoW32HandleBase *handle_data;
guint32 i, k;
- int thr_ret;
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&scan_mutex);
for(i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
if (private_handles [i]) {
}
}
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&scan_mutex);
}
#endif /* !defined(HOST_WIN32) */
if [[ ${CI_TAGS} == 'mobile_static' ]];
then
EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --with-runtime_preset=mobile_static";
+elif [[ ${CI_TAGS} == 'acceptance-tests' ]];
+ then
+ EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --prefix=${WORKSPACE}/tmp/mono-acceptance-tests --with-sgen-default-concurrent=yes";
elif [[ ${label} != w* ]] && [[ ${label} != 'debian-ppc64el' ]] && [[ ${label} != 'centos-s390x' ]];
then
# Override the defaults to skip profiles
# we don't run the test suite on Windows PRs, we just ensure the build succeeds, so end here
fi
-make check-ci
+if [[ ${CI_TAGS} == 'acceptance-tests' ]];
+then $(dirname "${BASH_SOURCE[0]}")/run-test-acceptance-tests.sh
+else make check-ci
+fi
\ No newline at end of file
--- /dev/null
+#!/bin/bash -e
+
+export TESTCMD=`dirname "${BASH_SOURCE[0]}"`/run-step.sh
+
+make install # Roslyn tests need a Mono installation
+
+LANG=en_US.UTF-8 ${TESTCMD} --label=check-ms-test-suite --timeout=30m make -C acceptance-tests check-ms-test-suite
+
+total_tests=$(find acceptance-tests/ -name TestResult*xml | xargs cat | grep -c "<test-case")
+if [ "$total_tests" -lt "1600" ]
+ then echo "*** NOT ENOUGH TEST RESULTS RECORDED, MARKING FAILURE ***"
+ exit 1
+fi
+
+${TESTCMD} --label=check-roslyn --timeout=30m make -C acceptance-tests check-roslyn PREFIX=${WORKSPACE}/tmp/mono-acceptance-tests
+rm -rf ${WORKSPACE}/tmp/mono-acceptance-tests # cleanup the Mono installation used for Roslyn tests
+
+${TESTCMD} --label=coreclr-compile-tests --timeout=80m --fatal make -C acceptance-tests coreclr-compile-tests
+${TESTCMD} --label=coreclr-runtest-basic --timeout=10m make -C acceptance-tests coreclr-runtest-basic
+${TESTCMD} --label=coreclr-runtest-coremanglib --timeout=10m make -C acceptance-tests coreclr-runtest-coremanglib
+${TESTCMD} --label=coreclr-gcstress --timeout=1200m make -C acceptance-tests coreclr-gcstress
${TESTCMD} --label=Microsoft.Build.Tasks --timeout=5m make -w -C mcs/class/Microsoft.Build.Tasks run-test
${TESTCMD} --label=Microsoft.Build.Utilities --timeout=5m make -w -C mcs/class/Microsoft.Build.Utilities run-test
${TESTCMD} --label=Mono.C5 --timeout=5m make -w -C mcs/class/Mono.C5 run-test
+${TESTCMD} --label=Mono.Tasklets --timeout=5m make -w -C mcs/class/Mono.Tasklets run-test
${TESTCMD} --label=System.Configuration --timeout=5m make -w -C mcs/class/System.Configuration run-test
${TESTCMD} --label=System.Transactions --timeout=5m make -w -C mcs/class/System.Transactions run-test
${TESTCMD} --label=System.Web.Extensions --timeout=5m make -w -C mcs/class/System.Web.Extensions run-test