column name and ordinal fix.
# Set the build profiles and options before things which use them
#
-AC_ARG_WITH(profile4_x, [ --with-profile4=yes,no If you want to install the 4.x FX (defaults to yes)], [], [with_profile4_x=default])
+AC_ARG_WITH(profile4_x, [ --with-profile4_x=yes,no If you want to install the 4.x FX (defaults to yes)], [], [with_profile4_x=default])
AC_ARG_WITH(monodroid, [ --with-monodroid=yes,no If you want to build the MonoDroid assemblies (defaults to no)], [], [with_monodroid=default])
AC_ARG_WITH(monotouch, [ --with-monotouch=yes,no If you want to build the Xamarin.iOS assemblies (defaults to no)], [], [with_monotouch=default])
AC_ARG_WITH(monotouch_watch, [ --with-monotouch_watch=yes,no If you want to build the Xamarin.WatchOS assemblies (defaults to no)],[], [with_monotouch_watch=default])
va_list args;
va_start (args, format);
- if (g_vasprintf (&msg, format, args) < 0)
+ if (g_vasprintf (&msg, format, args) < 0) {
+ va_end (args);
return;
+ }
va_end (args);
if (!stdout_handler)
va_list args;
va_start (args, format);
- if (g_vasprintf (&msg, format, args) < 0)
+ if (g_vasprintf (&msg, format, args) < 0) {
+ va_end (args);
return;
+ }
va_end (args);
if (!stderr_handler)
-Subproject commit 432738a3c938b4f751307301c6aa07f2027a8864
+Subproject commit c06ac6b33d3e7442ad878488b9d1100127eff998
-Subproject commit 4bc79a6da1f0ee538560b7e4d0caff46d3c86e4f
+Subproject commit dda48cd0343bddac6b3faf0c0498b680468cc3fd
executable.make \
gensources.sh \
library.make \
- nunit-summary.xsl \
rules.make \
tests.make \
$(COMMON_SRCS:%=common/%) \
CODEPAGE = 65001
RUNTIME_FLAGS =
-TEST_HARNESS = $(topdir)/class/lib/$(PROFILE)/$(PARENT_PROFILE)nunit-console.exe
+TEST_HARNESS = $(topdir)/class/lib/$(PROFILE)/$(PARENT_PROFILE)nunit-lite-console.exe
MCS_FLAGS =
MBAS_FLAGS = $(PLATFORM_DEBUG_FLAGS)
LIBRARY_FLAGS = /noconfig
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-<xsl:output method='text'/>
-
-<xsl:template match="/">
- <xsl:apply-templates/>
-</xsl:template>
-
-<xsl:template match="test-results">
-<xsl:text>Tests run: </xsl:text>
-<xsl:value-of select="@total"/>
-<xsl:text>, Failures: </xsl:text>
-<xsl:value-of select="@failures"/>
-<xsl:text>, Not run: </xsl:text>
-<xsl:value-of select="@not-run"/>
-<xsl:text>, Time: </xsl:text>
-<xsl:value-of select="test-suite/@time"/>
-<xsl:text> seconds
-</xsl:text>
-<xsl:text>
-</xsl:text>
-
-<xsl:if test="//test-suite[failure]"><xsl:text>Test Fixture SetUp Failures:
-</xsl:text></xsl:if>
-<xsl:apply-templates select="//test-suite[failure]"/>
-<xsl:if test="//test-case[failure]"><xsl:text>Test Case Failures:
-</xsl:text></xsl:if>
-<xsl:apply-templates select="//test-case[failure]"/>
-<xsl:if test="//test-case[@executed='False']"><xsl:text>Tests not run:
-</xsl:text></xsl:if>
-<xsl:apply-templates select="//test-case[@executed='False']"/>
-<xsl:text disable-output-escaping='yes'>
</xsl:text>
-</xsl:template>
-
-<xsl:template match="test-case|test-suite">
- <xsl:value-of select="position()"/><xsl:text>) </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text> : </xsl:text>
- <xsl:value-of select="child::node()/message"/>
-<xsl:text disable-output-escaping='yes'>
</xsl:text>
- <xsl:if test="failure">
- <xsl:value-of select="failure/stack-trace"/>
-<xsl:text>
-</xsl:text>
- </xsl:if>
-</xsl:template>
-
-</xsl:stylesheet>
PLATFORM_MCS_FLAGS = /nologo
PLATFORM_RUNTIME =
PLATFORM_CORLIB = mscorlib.dll
-PLATFORM_TEST_HARNESS_EXCLUDES =
+PLATFORM_TEST_HARNESS_EXCLUDES = NotOnWindows,
EXTERNAL_MCS = mcs
EXTERNAL_MBAS = vbc.exe
$(PLATFORM_DEBUG_FLAGS)
FRAMEWORK_VERSION = 2.1
-NUNIT_LITE = yes
# the tuner takes care of the install
NO_INSTALL = yes
-nowarn:1699 \
-nostdlib \
$(DEFAULT_REFERENCES) \
- $(PLATFORM_DEBUG_FLAGS)
+ $(PLATFORM_DEBUG_FLAGS) \
+ $(MONOTOUCH_MCS_FLAGS)
FRAMEWORK_VERSION = 2.1
-nowarn:1699 \
-nostdlib \
$(DEFAULT_REFERENCES) \
- $(PLATFORM_DEBUG_FLAGS)
+ $(PLATFORM_DEBUG_FLAGS) \
+ $(XAMMAC_MCS_FLAGS)
FRAMEWORK_VERSION = 2.1
NO_TEST = yes
NO_INSTALL = yes
MOBILE_DYNAMIC = yes
MOBILE_PROFILE = yes
+
+PROFILE_DISABLE_BTLS=1
include $(topdir)/build/profiles/net_4_x.make
+
PROFILE_MCS_FLAGS += \
-d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK \
-d:NO_SYSTEM_DRAWING_DEPENDENCY \
-d:NO_WINFORMS_DEPENDENCY \
-d:NO_SYSTEM_WEB_DEPENDENCY \
-d:XAMMAC_4_5 \
- -d:XAMARIN_MODERN
+ -d:XAMARIN_MODERN \
+ $(XAMMAC_MCS_FLAGS)
+
XAMMAC_4_5=1
NO_WINDOWS_BASE=1
NO_SYSTEM_WEB_DEPENDENCY=1
NO_SYSTEM_SERVICEMODEL_ACTIVATION_DEPENDENCY=1
NO_SYSTEM_DESIGN_DEPENDENCY=1
NO_SYSTEM_DIRECTORY_SERVICES_DEPENDENCY=1
+
+PROFILE_DISABLE_BTLS=1
include $(topdir)/build/profiles/$(PROFILE).make
-# If the profile is using nunit-lite, use it
-ifdef NUNIT_LITE
-TEST_HARNESS=$(topdir)/class/lib/$(PROFILE)/nunit-lite-console.exe
-endif
-
-# Make sure propagates
-export TEST_HARNESS
-
-# If the profile is using nunit-lite, use it
-ifdef NUNIT_LITE
-TEST_HARNESS=$(topdir)/class/lib/$(PROFILE)/nunit-lite-console.exe
-endif
-
-# Make sure propagates
-export TEST_HARNESS
-
ifdef BCL_OPTIMIZE
PROFILE_MCS_FLAGS += -optimize
endif
## Unit test support
ifndef NO_TEST
-ifdef NUNIT_LITE
test_nunit_lib = nunitlite.dll
-else
-test_nunit_lib = nunit.framework.dll nunit.core.dll nunit.util.dll nunit.mocks.dll
-endif
TEST_LIB_MCS_FLAGS = $(patsubst %,-r:$(topdir)/class/lib/$(PROFILE)/%.dll,$(TEST_LIB_REFS))
$(test_nunit_dep): $(topdir)/build/deps/nunit-$(PROFILE).stamp
@if test -f $@; then :; else rm -f $<; $(MAKE) $<; fi
-ifdef NUNIT_LITE
$(topdir)/build/deps/nunit-$(PROFILE).stamp:
ifndef PARENT_PROFILE
cd ${topdir}/tools/nunit-lite && $(MAKE)
endif
echo "stamp" >$@
-else
-$(topdir)/build/deps/nunit-$(PROFILE).stamp:
-ifndef PARENT_PROFILE
- cd ${topdir}/nunit24 && $(MAKE)
-endif
- echo "stamp" >$@
-endif
tests_CLEAN_FILES += $(topdir)/build/deps/nunit-$(PROFILE).stamp
endif
TEST_HARNESS_EXCLUDES = -exclude=$(PLATFORM_TEST_HARNESS_EXCLUDES)$(PROFILE_TEST_HARNESS_EXCLUDES)NotWorking,ValueAdd,CAS,InetAccess
TEST_HARNESS_EXCLUDES_ONDOTNET = /exclude:$(PLATFORM_TEST_HARNESS_EXCLUDES)$(PROFILE_TEST_HARNESS_EXCLUDES)NotDotNet,CAS
-ifdef NUNIT_LITE
NOSHADOW_FLAG =
-NUNIT_XML_FLAG = -format:nunit2 -result:
-OUTPUT_FILE_FLAG=-out
-else
-OUTPUT_FILE_FLAG=-output
-NOSHADOW_FLAG = -noshadow
-NUNIT_XML_FLAG = -xml=
-endif
-
-ifdef NUNIT_LITE
-NOSHADOW_FLAG =
-NUNIT_XML_FLAG = -format:nunit2 -result:
-OUTPUT_FILE_FLAG=-out
-else
-OUTPUT_FILE_FLAG=-output
-NOSHADOW_FLAG = -noshadow
-NUNIT_XML_FLAG = -xml=
-endif
-
-ifdef TEST_HARNESS_VERBOSE
-TEST_HARNESS_OUTPUT = -labels
-TEST_HARNESS_OUTPUT_ONDOTNET = -labels
-TEST_HARNESS_POSTPROC = :
-TEST_HARNESS_POSTPROC_ONDOTNET = :
-else
-TEST_HARNESS_OUTPUT = $(OUTPUT_FILE_FLAG)=TestResult-$(PROFILE).log
-TEST_HARNESS_OUTPUT_ONDOTNET = $(OUTPUT_FILE_FLAG)=TestResult-ondotnet-$(PROFILE).log
-TEST_HARNESS_POSTPROC = (echo ''; cat TestResult-$(PROFILE).log) | sed '1,/^Tests run: /d'; xsltproc $(topdir)/build/nunit-summary.xsl TestResult-$(PROFILE).xml >> TestResult-$(PROFILE).log
-TEST_HARNESS_POSTPROC_ONDOTNET = (echo ''; cat TestResult-ondotnet-$(PROFILE).log) | sed '1,/^Tests run: /d'; xsltproc $(topdir)/build/nunit-summary.xsl TestResult-ondotnet-$(PROFILE).xml >> TestResult-ondotnet-$(PROFILE).log
-endif
ifdef FIXTURE
-ifdef NUNIT_LITE
FIXTURE_ARG = -test=MonoTests.$(FIXTURE)
-else
-FIXTURE_ARG = -fixture=MonoTests.$(FIXTURE)
-endif
endif
ifdef TESTNAME
-ifdef NUNIT_LITE
TESTNAME_ARG = -test=MonoTests.$(TESTNAME)
-else
-TESTNAME_ARG = -run=MonoTests.$(TESTNAME)
endif
+
+ifdef TEST_HARNESS_VERBOSE
+LABELS_ARG = -labels
endif
ifdef ALWAYS_AOT
endif # ALWAYS_AOT
+NUNITLITE_CONFIG_FILE=$(topdir)/class/lib/$(PROFILE)/$(PARENT_PROFILE)nunit-lite-console.exe.config
+
+patch-nunitlite-appconfig:
+ cp -f $(topdir)/tools/nunit-lite/nunit-lite-console/nunit-lite-console.exe.config.tmpl $(NUNITLITE_CONFIG_FILE)
+ifdef TEST_NUNITLITE_APP_CONFIG_GLOBAL
+ sed -i -e "/__INSERT_CUSTOM_APP_CONFIG_GLOBAL__/r $(TEST_NUNITLITE_APP_CONFIG_GLOBAL)" $(NUNITLITE_CONFIG_FILE)
+endif
+ifdef TEST_NUNITLITE_APP_CONFIG_RUNTIME
+ sed -i -e "/__INSERT_CUSTOM_APP_CONFIG_RUNTIME__/r $(TEST_NUNITLITE_APP_CONFIG_RUNTIME)" $(NUNITLITE_CONFIG_FILE)
+endif
+
## FIXME: i18n problem in the 'sed' command below
-run-test-lib: test-local test-local-aot-compile
+run-test-lib: test-local test-local-aot-compile patch-nunitlite-appconfig
ok=:; \
- PATH="$(TEST_RUNTIME_WRAPPERS_PATH):$(PATH)" MONO_REGISTRY_PATH="$(HOME)/.mono/registry" MONO_TESTS_IN_PROGRESS="yes" $(TEST_RUNTIME) $(RUNTIME_FLAGS) $(AOT_RUN_FLAGS) $(TEST_HARNESS) $(test_assemblies) $(NOSHADOW_FLAG) $(TEST_HARNESS_FLAGS) $(LOCAL_TEST_HARNESS_FLAGS) $(TEST_HARNESS_EXCLUDES) $(TEST_HARNESS_OUTPUT) $(NUNIT_XML_FLAG)TestResult-$(PROFILE).xml $(FIXTURE_ARG) $(TESTNAME_ARG)|| ok=false; \
+ PATH="$(TEST_RUNTIME_WRAPPERS_PATH):$(PATH)" MONO_REGISTRY_PATH="$(HOME)/.mono/registry" MONO_TESTS_IN_PROGRESS="yes" $(TEST_RUNTIME) $(RUNTIME_FLAGS) $(AOT_RUN_FLAGS) $(TEST_HARNESS) $(test_assemblies) $(NOSHADOW_FLAG) $(TEST_HARNESS_FLAGS) $(LOCAL_TEST_HARNESS_FLAGS) $(TEST_HARNESS_EXCLUDES) $(LABELS_ARG) -format:nunit2 -result:TestResult-$(PROFILE).xml $(FIXTURE_ARG) $(TESTNAME_ARG)|| ok=false; \
if [ ! -f "TestResult-$(PROFILE).xml" ]; then echo "<?xml version='1.0' encoding='utf-8'?><test-results failures='1' total='1' not-run='0' name='bcl-tests' date='$$(date +%F)' time='$$(date +%T)'><test-suite name='$(strip $(test_assemblies))' success='False' time='0'><results><test-case name='crash' executed='True' success='False' time='0'><failure><message>The test runner didn't produce a test result XML, probably due to a crash of the runtime. Check the log for more details.</message><stack-trace></stack-trace></failure></test-case></results></test-suite></test-results>" > TestResult-$(PROFILE).xml; fi; \
- $(TEST_HARNESS_POSTPROC) ; $$ok
+ $$ok
## Instructs compiler to compile to target .net execution, it can be usefull in rare cases when runtime detection is not possible
run-test-ondotnet-lib: LOCAL_TEST_COMPILER_ONDOTNET_FLAGS:=-d:RUN_ONDOTNET
run-test-ondotnet-lib: test-local
ok=:; \
- $(TEST_HARNESS) $(test_assemblies) $(NOSHADOW_FLAG) $(TEST_HARNESS_FLAGS) $(LOCAL_TEST_HARNESS_ONDOTNET_FLAGS) $(TEST_HARNESS_EXCLUDES_ONDOTNET) $(TEST_HARNESS_OUTPUT_ONDOTNET) $(NUNIT_XML_FLAG)=TestResult-ondotnet-$(PROFILE).xml $(FIXTURE_ARG) $(TESTNAME_ARG) || ok=false; \
- $(TEST_HARNESS_POSTPROC_ONDOTNET) ; $$ok
+ $(TEST_HARNESS) $(test_assemblies) $(NOSHADOW_FLAG) $(TEST_HARNESS_FLAGS) $(LOCAL_TEST_HARNESS_ONDOTNET_FLAGS) $(TEST_HARNESS_EXCLUDES_ONDOTNET) $(LABELS_ARG) -format:nunit2 -result:TestResult-ondotnet-$(PROFILE).xml $(FIXTURE_ARG) $(TESTNAME_ARG) || ok=false; \
+ $$ok
endif # test_assemblies
endif
+.PHONY: patch-nunitlite-appconfig
/Test/resources/*.proj
+Test/test-config-file-*
TEST_MCS_FLAGS =
TEST_LIB_REFS = $(XBUILD_FRAMEWORK) $(XBUILD_UTILITIES) $(PARENT_PROFILE)System.Xml
+TEST_NUNITLITE_APP_CONFIG_RUNTIME=Test/test-config-file-$(PROFILE)
EXTRA_DISTFILES = \
Test/resources/TestTasks.cs \
--- /dev/null
+Test/test-config-file-*
LIB_REFS = $(PARENT_PROFILE)System
LIB_MCS_FLAGS =
+TEST_NUNITLITE_APP_CONFIG_RUNTIME=Test/test-config-file-$(PROFILE)
+
EXTRA_DISTFILES = \
Mono.XBuild.Framework/AssemblyLoadInfo.cs
/Test/resources/*.proj
+Test/test-config-file-*
TEST_MCS_FLAGS =
TEST_LIB_REFS = $(PARENT_PROFILE)System.Xml $(XBUILD_ENGINE) $(XBUILD_FRAMEWORK) $(XBUILD_TASKS) $(XBUILD_UTILITIES) $(PARENT_PROFILE)System.Core
+TEST_NUNITLITE_APP_CONFIG_RUNTIME=Test/test-config-file-$(PROFILE)
+
ifeq (4, $(FRAMEWORK_VERSION_MAJOR))
TEST_LIB_REFS += Microsoft.Build
endif
Test/resources/test.cs \
Test/resources/Sample.cs \
Test/resources/Sample.vb \
- Test/resources/junk.txt \
- Test/test-config-file*
+ Test/resources/junk.txt
Test/resources/test.dll: Test/resources/test.cs
$(CSCOMPILE) -target:library /out:$@ $<
+++ /dev/null
-<?xml version ="1.0"?>
-<configuration>
- <runtime>
- <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
- <dependentAssembly>
- <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
- <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="4.0.0.0"/>
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="Microsoft.Build.Engine" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
- <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="4.0.0.0"/>
- </dependentAssembly>
- </assemblyBinding>
- </runtime>
-</configuration>
--- /dev/null
+Test/test-config-file-*
TEST_LIB_REFS = $(XBUILD_ENGINE) $(XBUILD_FRAMEWORK) $(PARENT_PROFILE)System $(PARENT_PROFILE)System.Core
TEST_MCS_FLAGS = $(TEST_RESX_RESOURCES:%=-resource:%)
+TEST_NUNITLITE_APP_CONFIG_RUNTIME=Test/test-config-file-$(PROFILE)
include $(XBUILD_DIR)/xbuild_test.make
include ../../build/library.make
Microsoft.Build.Internal/ExpressionParser.cs
Microsoft.Build.Internal/y.output
Test/FunctionalTestProject*.csproj
+Test/test-config-file-*
LIB_REFS = $(PARENT_PROFILE)System $(PARENT_PROFILE)System.Core $(PARENT_PROFILE)System.Xml Microsoft.Build.Engine Microsoft.Build.Framework
LIB_MCS_FLAGS = \
/d:MICROSOFT_BUILD_DLL
-
+
TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
TEST_LIB_REFS = $(XBUILD_UTILITIES)
+TEST_NUNITLITE_APP_CONFIG_RUNTIME=Test/test-config-file-$(PROFILE)
EXTRA_DISTFILES = \
Microsoft.Build.Internal/ExpressionParser.jay \
if (!queued_builds.TryDequeue (out build))
continue;
StartOneBuild (build);
+ } catch (ThreadAbortException) {
+ // do nothing
+ break;
} catch (Exception ex) {
// FIXME: I guess INodeLogger should be used instead.
Console.Error.WriteLine ("Uncaught build node exception occured");
+../../test-helpers/NunitHelpers.cs
FunctionalTest.cs
Microsoft.Build.Construction/ProjectItemElementTest.cs
Microsoft.Build.Construction/ProjectRootElementTest.cs
+../../test-helpers/NunitHelpers.cs
RewriteAndLoad.cs
TestCCRewrite.cs
public void DefineMethod (MonoSymbolFile file, int token)
{
var blocks = Blocks;
+ if (blocks.Length > 0) {
+ //
+ // When index is provided by user it can be inserted in
+ // any order but mdb format does not store its value. It
+ // uses stored order as the index instead.
+ //
+ var sorted = new List<CodeBlockEntry> (blocks.Length);
+ int max_index = 0;
+ for (int i = 0; i < blocks.Length; ++i) {
+ max_index = System.Math.Max (max_index, blocks [i].Index);
+ }
+
+ for (int i = 0; i < max_index; ++i) {
+ var scope_index = i + 1;
+
+ //
+ // Common fast path
+ //
+ if (i < blocks.Length && blocks [i].Index == scope_index) {
+ sorted.Add (blocks [i]);
+ continue;
+ }
+
+ bool found = false;
+ for (int ii = 0; ii < blocks.Length; ++ii) {
+ if (blocks [ii].Index == scope_index) {
+ sorted.Add (blocks [ii]);
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ //
+ // Ideally this should never happen but with current design we can
+ // generate scope index for unreachable code before reachable code
+ //
+ sorted.Add (new CodeBlockEntry (scope_index, -1, CodeBlockEntry.Type.CompilerGenerated, 0));
+ }
- //
- // When index is provided by user it can be inserted in
- // any order but mdb format does not store its value. It
- // uses store order instead as the index.
- //
- Array.Sort (blocks, (x, y) => x.Index.CompareTo (y.Index));
+ blocks = sorted.ToArray ();
+ //for (int i = 0; i < blocks.Length; ++i) {
+ // if (blocks [i].Index - 1 != i)
+ // throw new ArgumentException ("CodeBlocks cannot be converted to mdb format");
+ //}
+ }
var entry = new MethodEntry (
file, _comp_unit.Entry, token, ScopeVariables,
+../../test-helpers/NunitHelpers.cs
Mono.Collections.Concurrent/CollectionStressTestHelper.cs
Mono.Collections.Concurrent/ConcurrentSkipListTests.cs
Mono.Threading/ParallelTestHelper.cs
+../../test-helpers/NunitHelpers.cs
Mono.Unix/ReadlinkTest.cs
Mono.Unix/StdioFileStreamTest.cs
Mono.Unix/UnixEncodingTest.cs
//
using NUnit.Framework;
-#if !MONODROID
-using NUnit.Framework.SyntaxHelpers;
-#endif
+
using System;
using System.Text;
using System.Threading;
namespace MonoTests.Mono.Unix.Native {
[TestFixture]
- [Category ("NotOnMac")]
+ [Category ("NotOnMac"), Category ("NotOnWindows")]
public class RealTimeSignumTest
{
[Test]
namespace MonoTests.Mono.Unix.Native
{
- [TestFixture, Category ("NotDotNet")]
+ [TestFixture, Category ("NotDotNet"), Category ("NotOnWindows")]
public class SocketTest {
string TempFolder;
namespace MonoTests.Mono.Unix.Native {
- [TestFixture]
+ [TestFixture, Category ("NotOnWindows")]
public class StdlibTest
{
private class SignalTest {
namespace MonoTests.Mono.Unix
{
- [TestFixture, Category ("NotDotNet")]
+ [TestFixture, Category ("NotDotNet"), Category ("NotOnWindows")]
public class ReadlinkTest {
static string[] Targets = {
long r = Syscall.readlink (link, buf);
if (r < 0)
UnixMarshal.ThrowExceptionForLastError ();
- Assert.GreaterOrEqual (buf.Length, r);
+ AssertHelper.GreaterOrEqual (buf.Length, r);
if (r == buf.Length)
buf = new byte[checked (buf.Length * 2)];
else
long r = Syscall.readlinkat (TempFD, "link", buf);
if (r < 0)
UnixMarshal.ThrowExceptionForLastError ();
- Assert.GreaterOrEqual (buf.Length, r);
+ AssertHelper.GreaterOrEqual (buf.Length, r);
if (r == buf.Length)
buf = new byte[checked (buf.Length * 2)];
else
if (r < 0)
UnixMarshal.ThrowExceptionForLastError ();
Assert.AreEqual (r, sb.Length);
- Assert.GreaterOrEqual (sb.Capacity, r);
+ AssertHelper.GreaterOrEqual (sb.Capacity, r);
if (r == sb.Capacity)
checked { sb.Capacity *= 2; }
else
if (r < 0)
UnixMarshal.ThrowExceptionForLastError ();
Assert.AreEqual (r, sb.Length);
- Assert.GreaterOrEqual (sb.Capacity, r);
+ AssertHelper.GreaterOrEqual (sb.Capacity, r);
if (r == sb.Capacity)
checked { sb.Capacity *= 2; }
else
namespace MonoTests.Mono.Unix {
- [TestFixture]
+ [TestFixture, Category ("NotOnWindows")]
public class UnixEndPointTest {
// Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=35004
namespace MonoTests.Mono.Unix {
- [TestFixture, Category ("NotDotNet")]
+ [TestFixture, Category ("NotDotNet"), Category ("NotOnWindows")]
public class UnixGroupTest
{
[Test]
namespace MonoTests.Mono.Unix {
- [TestFixture]
+ [TestFixture, Category ("NotOnWindows")]
public class UnixListenerTest {
// test that a socket file is created and deleted by the UnixListener
}
}
- [TestFixture]
+ [TestFixture, Category ("NotOnWindows")]
public class UnixMarshalTest {
#if false
public static void Main ()
namespace MonoTests.Mono.Unix
{
- [TestFixture, Category ("NotDotNet")]
+ [TestFixture, Category ("NotDotNet"), Category ("NotOnWindows")]
public class UnixPathTest {
private static readonly char DSC = UnixPath.DirectorySeparatorChar;
//
using NUnit.Framework;
-#if !MONODROID
-using NUnit.Framework.SyntaxHelpers;
-#endif
+
using System;
using System.Text;
using System.Threading;
using Mono.Unix;
using Mono.Unix.Android;
using Mono.Unix.Native;
-#if !MONODROID
-namespace NUnit.Framework.SyntaxHelpers { class Dummy {} }
-#endif
+
namespace MonoTests.Mono.Unix {
- [TestFixture]
+ [TestFixture, Category ("NotOnWindows")]
public class UnixSignalTest {
// helper method to create a thread waiting on a UnixSignal
namespace MonoTests.Mono.Unix {
- [TestFixture, Category ("NotDotNet")]
+ [TestFixture, Category ("NotDotNet"), Category ("NotOnWindows")]
public class UnixUserTest
{
[Test]
include ../../build/rules.make
LIBRARY = Mono.Reactive.Testing.dll
-LIB_REFS = System System.Core System.Reactive.Interfaces System.Reactive.Core System.Reactive.Linq System.Reactive.PlatformServices System.Reactive.Providers System.Reactive.Runtime.Remoting System.Reactive.Experimental System.Reactive.Windows.Forms System.Reactive.Windows.Threading System.Reactive.Observable.Aliases System.Windows.Forms WindowsBase nunit.framework
+LIB_REFS = System System.Core System.Reactive.Interfaces System.Reactive.Core System.Reactive.Linq System.Reactive.PlatformServices System.Reactive.Providers System.Reactive.Runtime.Remoting System.Reactive.Experimental System.Reactive.Windows.Forms System.Reactive.Windows.Threading System.Reactive.Observable.Aliases System.Windows.Forms WindowsBase nunitlite
LIB_MCS_FLAGS = \
@more_build_args \
-d:NUNIT -d:MONO -d:DESKTOPCLR
SUBDIRS =
include ../../../../../build/rules.make
-LOCAL_MCS_FLAGS = -r:System.dll -r:Mono.Security.dll -r:../../../../lib/net_4_x/nunit.framework.dll
+LOCAL_MCS_FLAGS = -r:System.dll -r:Mono.Security.dll -r:../../../../lib/net_4_x/nunitlite.dll
all-local install-local uninstall-local:
--- /dev/null
+Test/test-config-file-*
LIB_REFS = $(PARENT_PROFILE)System $(PARENT_PROFILE)System.Xml
LIB_MCS_FLAGS =
+TEST_NUNITLITE_APP_CONFIG_RUNTIME=Test/test-config-file-$(PROFILE)
+
include $(XBUILD_DIR)/xbuild_test.make
include ../../build/library.make
+../../test-helpers/NunitHelpers.cs
Mono.XBuild.Tasks/PcFileCacheTest.cs
LIB_MCS_FLAGS = -nowarn:618
TEST_MCS_FLAGS =
TEST_LIB_REFS = System.Xml System
+TEST_NUNITLITE_APP_CONFIG_GLOBAL=Test/test-config-file
include ../../build/library.make
$(build_lib): $(configuration_library_deps)
+test-local:
+ cp Test/appSettings.config $(dir $(NUNITLITE_CONFIG_FILE))/Test-appSettings.config
+
.NOTPARALLEL: $(configuration_library_deps)
$(secxml_libdir)/System.dll:
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<configuration>
- <connectionStrings>
- <add name="test-connstring"
- connectionString="Server=(local);Initial Catalog=someDb;User Id=someUser;Password=somePassword;Application Name=someAppName;Min Pool Size=5;Max Pool Size=500;Connect Timeout=10;Connection Lifetime=29;" />
- </connectionStrings>
- <appSettings file="Test/appSettings.config" />
-</configuration>
{
Directory.SetCurrentDirectory (tempFolder);
- var currentAssembly = Assembly.GetExecutingAssembly ().Location;
+ var currentAssembly = TestUtil.ThisApplicationPath;
var config = ConfigurationManager.OpenExeConfiguration (currentAssembly);
- Assert.AreEqual ("Test/appSettings.config", config.AppSettings.File, "#A01");
+ Assert.AreEqual ("Test-appSettings.config", config.AppSettings.File, "#A01");
Assert.AreEqual ("foo", ConfigurationSettings.AppSettings["TestKey1"], "#A02");
Assert.AreEqual ("bar", ConfigurationSettings.AppSettings["TestKey2"], "#A03");
}
[Test]
public void exePath_UserLevelNone ()
{
- string basedir = AppDomain.CurrentDomain.BaseDirectory;
- string name = TestUtil.ThisDllName;
+ string name = TestUtil.ThisApplicationPath;
SysConfig config = ConfigurationManager.OpenExeConfiguration (name);
- Assert.AreEqual (Path.Combine (basedir, name + ".config"), config.FilePath);
+ Assert.AreEqual (TestUtil.ThisApplicationPath + ".config", config.FilePath);
}
[Test]
[Test]
public void TestConnectionStringRetrieval ()
{
- var currentAssembly = Assembly.GetExecutingAssembly().Location;
- Assert.IsTrue (File.Exists (currentAssembly + ".config"),
- String.Format ("This test cannot succeed without the .config file being in the same place as the assembly ({0})",
- currentAssembly));
-
var connStringObj = ConfigurationManager.ConnectionStrings ["test-connstring"];
Assert.IsNotNull (connStringObj);
var connString = connStringObj.ConnectionString;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
namespace MonoTests.System.Configuration {
using Util;
}
}
- public static string ThisDllName {
+ public static string ThisApplicationPath {
get {
- var asm = Assembly.GetCallingAssembly ();
- return Path.GetFileName (asm.Location);
+ var asm = Assembly.GetEntryAssembly ();
+ return asm.Location;
}
}
public static string ThisConfigFileName {
get {
- var asm = Assembly.GetCallingAssembly ();
- var exe = Path.GetFileName (asm.Location);
+ var exe = Path.GetFileName (ThisApplicationPath);
return exe + ".config";
}
}
--- /dev/null
+ <connectionStrings>
+ <add name="test-connstring"
+ connectionString="Server=(local);Initial Catalog=someDb;User Id=someUser;Password=somePassword;Application Name=someAppName;Min Pool Size=5;Max Pool Size=500;Connect Timeout=10;Connection Lifetime=29;" />
+ </connectionStrings>
+ <appSettings file="Test-appSettings.config" />
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<configuration>
- <connectionStrings>
- <add name="test-connstring"
- connectionString="Server=(local);Initial Catalog=someDb;User Id=someUser;Password=somePassword;Application Name=someAppName;Min Pool Size=5;Max Pool Size=500;Connect Timeout=10;Connection Lifetime=29;" />
- </connectionStrings>
- <appSettings file="Test/appSettings.config" />
-</configuration>
Initialize ((ulong)size);
}
+ internal void Flush () {
+ MemoryMapImpl.Flush (this.mmap_handle);
+ }
+
protected override bool ReleaseHandle () {
if (this.handle != (IntPtr) (-1))
return MemoryMapImpl.Unmap (this.mmap_handle);
case 1:
return new ArgumentException ("A positive capacity must be specified for a Memory Mapped File backed by an empty file.");
case 2:
- return new ArgumentOutOfRangeException ("The capacity may not be smaller than the file size.");
+ return new ArgumentOutOfRangeException ("capacity", "The capacity may not be smaller than the file size.");
case 3:
return new FileNotFoundException (path);
case 4:
return new ArgumentException ("Invalid FileMode value.");
case 9:
return new IOException ("Could not map file");
+ case 10:
+ return new UnauthorizedAccessException ("Access to the path is denied.");
+ case 11:
+ return new ArgumentOutOfRangeException ("capacity", "The capacity cannot be greater than the size of the system's logical address space.");
default:
return new IOException ("Failed with unknown error code " + error);
}
if (mode == FileMode.Append)
throw new ArgumentException ("mode");
- IntPtr handle = MemoryMapImpl.OpenFile (path, mode, null, out capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages);
+ IntPtr handle = MemoryMapImpl.OpenFile (path, mode, null, out capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None);
return new MemoryMappedFile () {
handle = handle,
if (capacity < 0)
throw new ArgumentOutOfRangeException ("capacity");
- IntPtr handle = MemoryMapImpl.OpenFile (path, mode, mapName, out capacity, access, MemoryMappedFileOptions.DelayAllocatePages);
+ IntPtr handle = MemoryMapImpl.OpenFile (path, mode, mapName, out capacity, access, MemoryMappedFileOptions.None);
return new MemoryMappedFile () {
handle = handle,
if ((!MonoUtil.IsUnix && capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
throw new ArgumentException ("capacity");
- IntPtr handle = MemoryMapImpl.OpenHandle (fileStream.SafeFileHandle.DangerousGetHandle (), mapName, out capacity, access, MemoryMappedFileOptions.DelayAllocatePages);
+ IntPtr handle = MemoryMapImpl.OpenHandle (fileStream.SafeFileHandle.DangerousGetHandle (), mapName, out capacity, access, MemoryMappedFileOptions.None);
MemoryMapImpl.ConfigureHandleInheritability (handle, inheritability);
if ((!MonoUtil.IsUnix && capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
throw new ArgumentException ("capacity");
- IntPtr handle = MemoryMapImpl.OpenHandle (fileStream.SafeFileHandle.DangerousGetHandle (), mapName, out capacity, access, MemoryMappedFileOptions.DelayAllocatePages);
+ IntPtr handle = MemoryMapImpl.OpenHandle (fileStream.SafeFileHandle.DangerousGetHandle (), mapName, out capacity, access, MemoryMappedFileOptions.None);
MemoryMapImpl.ConfigureHandleInheritability (handle, inheritability);
[MonoLimitation ("Named mappings scope is process local")]
public static MemoryMappedFile CreateNew (string mapName, long capacity)
{
- return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, null, HandleInheritability.None);
+ return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, null, HandleInheritability.None);
}
[MonoLimitation ("Named mappings scope is process local")]
public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access)
{
- return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, HandleInheritability.None);
+ return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None);
}
[MonoLimitation ("Named mappings scope is process local; options is ignored")]
[MonoLimitation ("Named mappings scope is process local")]
public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access)
{
- return CreateOrOpen (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, HandleInheritability.None);
+ return CreateOrOpen (mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None);
}
[MonoLimitation ("Named mappings scope is process local")]
public void Flush (IntPtr capacity)
{
- MemoryMapImpl.Flush (m_viewHandle.DangerousGetHandle ());
+ m_viewHandle.Flush ();
}
protected virtual void Dispose (bool disposing)
return "test-" + named_index++;
}
-
+ static string baseTempDir = Path.Combine (Path.GetTempPath (), typeof (MemoryMappedFileTest).FullName);
static string tempDir = Path.Combine (Path.GetTempPath (), typeof (MemoryMappedFileTest).FullName);
string fname;
- [SetUp]
- protected void SetUp () {
- if (Directory.Exists (tempDir))
- Directory.Delete (tempDir, true);
+ [TestFixtureSetUp]
+ public void FixtureSetUp ()
+ {
+ try {
+ // Try to cleanup from any previous NUnit run.
+ Directory.Delete (baseTempDir, true);
+ } catch (Exception) {
+ }
+ }
+ [SetUp]
+ public void SetUp ()
+ {
+ int i = 0;
+ do {
+ tempDir = Path.Combine (baseTempDir, (++i).ToString());
+ } while (Directory.Exists (tempDir));
Directory.CreateDirectory (tempDir);
fname = Path.Combine (tempDir, "basic.txt");
}
[TearDown]
- protected void TearDown () {
- if (Directory.Exists (tempDir))
+ public void TearDown ()
+ {
+ try {
+ // This throws an exception under MS.NET and Mono on Windows,
+ // since the directory contains open files.
Directory.Delete (tempDir, true);
+ } catch (Exception) {
+ }
}
[Test]
public void CreateNew ()
{
// This must succeed
- MemoryMappedFile.CreateNew (Path.Combine (tempDir, "createNew.test"), 8192);
- }
-
- [Test]
- [ExpectedException (typeof (IOException))]
- public void CreateNew_OnExistingFile ()
- {
- // This must succeed
- MemoryMappedFile.CreateNew (Path.Combine (tempDir, "createNew.test"), 8192);
-
- // This should fail, the file exists
- MemoryMappedFile.CreateNew (Path.Combine (tempDir, "createNew.test"), 8192);
+ MemoryMappedFile.CreateNew (MkNamedMapping (), 8192);
}
// Call this twice, it should always work
[Test]
public void CreateOrOpen_Multiple ()
{
- MemoryMappedFile.CreateOrOpen (Path.Combine (tempDir, "createOrOpen.test"), 8192);
- MemoryMappedFile.CreateOrOpen (Path.Combine (tempDir, "createOrOpen.test"), 8192);
+ var name = MkNamedMapping ();
+ MemoryMappedFile.CreateOrOpen (name, 8192);
+ MemoryMappedFile.CreateOrOpen (name, 8192);
}
[Test]
// We are requesting fewer bytes to map.
MemoryMappedFile.CreateFromFile (f, FileMode.Open, "myMap", 4192);
}
-
+
[Test]
public void CreateFromFile_Null () {
AssertThrows<ArgumentNullException> (delegate () {
[Test]
public void NamedMappingToInvalidFile ()
{
+ if (Environment.OSVersion.Platform != PlatformID.Unix) {
+ Assert.Ignore ("Backslashes in mapping names are disallowed on .NET and Mono on Windows");
+ }
var fileName = Path.Combine (tempDir, "temp_file_123");
if (File.Exists (fileName))
File.Delete (fileName);
}
[Test]
- [ExpectedException(typeof(IOException))]
+ [ExpectedException(typeof(UnauthorizedAccessException))]
public void CreateViewStreamWithOffsetPastFileEnd ()
{
string f = Path.Combine (tempDir, "8192-file");
}
[Test]
- [ExpectedException(typeof(IOException))]
+ [ExpectedException(typeof(UnauthorizedAccessException))]
public void CreateViewStreamWithOffsetPastFileEnd2 ()
{
string f = Path.Combine (tempDir, "8192-file");
MemoryMappedViewStream stream = mappedFile.CreateViewStream (pageSize * 2, 0, MemoryMappedFileAccess.ReadWrite);
#if !MONOTOUCH
- Assert.AreEqual (stream.Capacity, Environment.SystemPageSize);
+ Assert.AreEqual (Environment.SystemPageSize, stream.Capacity);
#endif
stream.Write (new byte [pageSize], 0, pageSize);
}
File.WriteAllBytes (f, new byte [size]);
FileStream file = File.OpenRead (f);
- MemoryMappedFile.CreateFromFile (file, null, size, MemoryMappedFileAccess.ReadExecute, null, 0, false);
+ MemoryMappedFile.CreateFromFile (file, null, size, MemoryMappedFileAccess.Read, null, 0, false);
}
- }
-}
+ [Test]
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]
+ public void CreateNewLargerThanLogicalAddressSpace ()
+ {
+ if (IntPtr.Size != 4) {
+ Assert.Ignore ("Only applies to 32-bit systems");
+ }
+ MemoryMappedFile.CreateNew (MkNamedMapping (), (long) uint.MaxValue + 1);
+ }
+ [Test]
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]
+ public void CreateOrOpenLargerThanLogicalAddressSpace ()
+ {
+ if (IntPtr.Size != 4) {
+ Assert.Ignore ("Only applies to 32-bit systems");
+ }
+ MemoryMappedFile.CreateOrOpen (MkNamedMapping (), (long) uint.MaxValue + 1);
+ }
+
+ [Test]
+ public void NamedMappingWithDelayAllocatePages ()
+ {
+ var name = MkNamedMapping ();
+ using (var m0 = MemoryMappedFile.CreateNew(name, 4096, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, HandleInheritability.None)) {
+ using (MemoryMappedViewAccessor v0 = m0.CreateViewAccessor ()) {
+ Assert.AreEqual (0, v0.ReadInt32 (0));
+ }
+ }
+ }
+
+ }
+}
using System.Threading;
using NUnit.Framework;
using System.Linq;
-using NUnit.Framework.SyntaxHelpers;
using NUnit.Framework.Constraints;
using System.Diagnostics;
-namespace NUnit.Framework.SyntaxHelpers { class Dummy {} }
-
namespace MonoTests.System.Linq
{
[TestFixture]
--- /dev/null
+Northwind.db3
+
+../../test-helpers/NunitHelpers.cs
../examples/DbLinq.SQLite.Example/nwind/Northwind.cs
../src/DbLinq.Sqlite/Test/DirectDataContext.cs
../src/DbLinq.Sqlite/Test/TestBase_mono.cs
$(sqlite_tests): $(sqlite_tests_dep)
$(TEST_COMPILE) -target:library -out:$@ \
- -r:System.Data.dll -r:$(the_assembly) -r:Mono.Data.Sqlite $(test_nunit_ref) \
+ -r:$(topdir)/class/lib/$(PROFILE)/System.Data.dll -r:$(the_assembly) -r:$(topdir)/class/lib/$(PROFILE)/Mono.Data.Sqlite.dll -r:$(topdir)/class/lib/$(PROFILE)/System.Core.dll -r:$(topdir)/class/lib/$(PROFILE)/System.dll -r:$(topdir)/class/lib/$(PROFILE)/System.Xml.dll $(test_nunit_ref) \
$(TEST_MCS_FLAGS) -d:MONO_STRICT -d:SQLITE \
@$< $(TEST_SOURCES_WITH_SPACES)
test-sqlite: $(sqlite_tests)
RUN_TEST_COMMAND = \
- MONO_REGISTRY_PATH="$(HOME)/.mono/registry" $(TEST_RUNTIME) $(RUNTIME_FLAGS) $(TEST_HARNESS) $(1) -noshadow $(TEST_HARNESS_FLAGS) $(LOCAL_TEST_HARNESS_FLAGS) $(TEST_HARNESS_EXCLUDES) $(TEST_HARNESS_OUTPUT) -xml=TestResult-$(1:.dll=)-$(PROFILE).xml -out:TestResult-$(1:.dll=)-$(PROFILE).out $(FIXTURE_ARG) $(TESTNAME_ARG) ; \
- xsltproc $(topdir)/build/nunit-summary.xsl TestResult-$(1)-$(PROFILE).xml > TestResult-$(1:.dll=)-$(PROFILE).log
+ MONO_REGISTRY_PATH="$(HOME)/.mono/registry" $(TEST_RUNTIME) $(RUNTIME_FLAGS) $(TEST_HARNESS) $(1) $(TEST_HARNESS_FLAGS) $(LOCAL_TEST_HARNESS_FLAGS) $(TEST_HARNESS_EXCLUDES) $(TEST_HARNESS_OUTPUT) -labels -format:nunit2 -result=TestResult-$(1:.dll=)-$(PROFILE).xml $(FIXTURE_ARG) $(TESTNAME_ARG) ;
run-test-sqlite:
$(call RUN_TEST_COMMAND,$(sqlite_tests))
\r
\r
Assert.IsNotNull(dbCommand.CommandText);\r
- Assert.Greater(dbCommand.Parameters.Count, 0);\r
+ AssertHelper.Greater(dbCommand.Parameters.Count, 0);\r
}\r
}\r
}\r
Northwind db = CreateDB();\r
Expression<Func<Customer, bool>> predicate = c => c.City == "Paris";\r
int count = db.Customers.Count(predicate);\r
- Assert.Greater(count, 0); // Some databases have more than 1 customer in Paris\r
+ AssertHelper.Greater(count, 0); // Some databases have more than 1 customer in Paris\r
}\r
\r
/// <summary>\r
{\r
Northwind db = CreateDB();\r
int result = db.ExecuteCommand("SELECT count(*) FROM \"Products\"");\r
- Assert.Greater(result, 0, "Expecting some rows in Products table, got:" + result);\r
+ AssertHelper.Greater(result, 0, "Expecting some rows in Products table, got:" + result);\r
}\r
\r
/// <summary>\r
Northwind db = CreateDB();\r
int result = db.ExecuteCommand("SELECT count(*) FROM [Products] WHERE [ProductID]>{0}", 3);\r
//long iResult = base.ExecuteScalar(sql);\r
- Assert.Greater(result, 0, "Expecting some rows in Products table, got:" + result);\r
+ AssertHelper.Greater(result, 0, "Expecting some rows in Products table, got:" + result);\r
}\r
\r
}\r
string beforecountry = character.Country;\r
character.Country = "Burmuda";\r
\r
- Assert.Greater(db.GetChangeSet().Updates.Count, 0);\r
+ AssertHelper.Greater(db.GetChangeSet().Updates.Count, 0);\r
db.SubmitChanges();\r
\r
var character2 = db.Customers.First(c=>c.CustomerID==character.CustomerID);\r
\r
var q3 = q1.Union(q2);\r
\r
- Assert.Greater(q1.Count(), 0);\r
+ AssertHelper.Greater(q1.Count(), 0);\r
Assert.IsTrue(q1.Count() + q2.Count() >= q3.Count());\r
\r
}\r
var q = from p in db.Products select p;\r
List<Product> products = q.ToList();\r
int productCount = products.Count;\r
- Assert.Greater(productCount, 0, "Expected some products, got none");\r
+ AssertHelper.Greater(productCount, 0, "Expected some products, got none");\r
}\r
\r
#if !DEBUG && SQLITE\r
select p;\r
\r
int count = q.Count();\r
- Assert.Less(count, db.Customers.Count());\r
+ AssertHelper.Less(count, db.Customers.Count());\r
}\r
\r
[Test]\r
select p;\r
\r
int count = q.Count();\r
- Assert.Less(count, db.Customers.Count());\r
+ AssertHelper.Less(count, db.Customers.Count());\r
}\r
\r
[Test]\r
}\r
\r
[Test]\r
- [ExpectedException(ExceptionType=typeof(InvalidOperationException), ExpectedMessage="Data context options cannot be modified after results have been returned from a query.")]\r
+ [ExpectedException(typeof(InvalidOperationException), ExpectedMessage="Data context options cannot be modified after results have been returned from a query.")]\r
public void C13_Changing_ObjectTrackingEnabled2False()\r
{\r
Northwind db = CreateDB();\r
}\r
\r
[Test]\r
- [ExpectedException(ExceptionType = typeof(InvalidOperationException), ExpectedMessage = "Data context options cannot be modified after results have been returned from a query.")]\r
+ [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Data context options cannot be modified after results have been returned from a query.")]\r
public void C14_Changing_DeferredLoadingEnabled2False()\r
{\r
Northwind db = CreateDB();\r
}\r
\r
[Test]\r
- [ExpectedException(ExceptionType = typeof(InvalidOperationException), ExpectedMessage = "Object tracking is not enabled for the current data context instance.")]\r
+ [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Object tracking is not enabled for the current data context instance.")]\r
public void C15_SubmitChanges_DeferredLoadingEnabled_False()\r
{\r
Northwind db = CreateDB();\r
.Join(db.GetTable<EmployeeTerritory>(), t => t.TerritoryID, l => l.TerritoryID, (t, l) => l)\r
.Join(db.GetTable<Employee>().Where(e => e.EmployeeID > 0), l => l.EmployeeID, e => e.EmployeeID, (l, e) => e);\r
var employeeCount = q.Count();\r
- Assert.Greater(employeeCount, 0, "Expected any employees, got count=" + employeeCount);\r
+ AssertHelper.Greater(employeeCount, 0, "Expected any employees, got count=" + employeeCount);\r
}\r
\r
/// <summary>\r
\r
var q = from p in db.Products where p.ProductName == "Chai" select p.ProductID;\r
var productID = q.First();\r
- Assert.Greater(productID, 0, "Expected penID>0, got " + productID);\r
+ AssertHelper.Greater(productID, 0, "Expected penID>0, got " + productID);\r
}\r
\r
\r
\r
var q = from p in db.Products where p.ProductName == "Chai" select p.ProductID;\r
var productID = q.Last();\r
- Assert.Greater(productID, 0, "Expected penID>0, got " + productID);\r
+ AssertHelper.Greater(productID, 0, "Expected penID>0, got " + productID);\r
}\r
\r
#if !DEBUG && (POSTGRES || (MSSQL && !L2SQL))\r
{\r
//int compareNames = prevProductName.CompareTo(p.ProductName);\r
int compareNames = string.Compare(prevProductName, p.ProductName, stringComparisonType);\r
- Assert.Less(compareNames, 0, "When ordering by names, expected " + prevProductName + " to come after " + p.ProductName);\r
+ AssertHelper.Less(compareNames, 0, "When ordering by names, expected " + prevProductName + " to come after " + p.ProductName);\r
}\r
prevProductName = p.ProductName;\r
}\r
- //Assert.Greater(productID,0,"Expected penID>0, got "+productID);\r
+ //AssertHelper.Greater(productID,0,"Expected penID>0, got "+productID);\r
}\r
\r
[Test]\r
Northwind db = CreateDB();\r
//var q = from p in db.Products where "Chai"==p.ProductName select p.Order;\r
//List<Order> penOrders = q.ToList();\r
- //Assert.Greater(penOrders.Count,0,"Expected some orders for product 'Chai'");\r
+ //AssertHelper.Greater(penOrders.Count,0,"Expected some orders for product 'Chai'");\r
\r
var q =\r
from o in db.Orders\r
Assert.IsNotNull(co.c.City, "Expected non-null customer city");\r
Assert.IsNotNull(co.o, "Expected non-null order");\r
}\r
- Assert.Greater(list1.Count, 0, "Expected some orders for London customers");\r
+ AssertHelper.Greater(list1.Count, 0, "Expected some orders for London customers");\r
}\r
\r
[Test]\r
Assert.IsNotNull(co.c, "Expected non-null customer");\r
Assert.IsNotNull(co.o, "Expected non-null order");\r
}\r
- Assert.Greater(list1.Count, 0, "Expected some orders for London customers");\r
+ AssertHelper.Greater(list1.Count, 0, "Expected some orders for London customers");\r
}\r
\r
[Test]\r
where c.City == "London"\r
select new { c, o };\r
\r
- Assert.Greater(q.ToList().Count, 0, "Expected some orders for London customers");\r
+ AssertHelper.Greater(q.ToList().Count, 0, "Expected some orders for London customers");\r
}\r
\r
[Test]\r
#else\r
int expectedCount = 2; //Oracle, Mysql: 'Toilet Paper' and 'iPod'\r
#endif\r
- Assert.Greater(prods.Count, expectedCount, "Expected couple of products with letter 'p'");\r
+ AssertHelper.Greater(prods.Count, expectedCount, "Expected couple of products with letter 'p'");\r
}\r
\r
[Test]\r
).Take(5);\r
//var q = db.Products.Where( p=>p.ProductName.Contains("p")).Take(5);\r
List<Product> prods = q.ToList();\r
- Assert.Greater(prods.Count, 2, "Expected couple of products with letter 'p'");\r
+ AssertHelper.Greater(prods.Count, 2, "Expected couple of products with letter 'p'");\r
\r
var prodID0 = prods[0].ProductID;\r
var prodID1 = prods[1].ProductID;\r
- Assert.Greater(prodID0, prodID1, "Sorting is broken");\r
+ AssertHelper.Greater(prodID0, prodID1, "Sorting is broken");\r
}\r
\r
[Test]\r
{\r
var q = from p in db.Products select p;\r
int productCount = q.Count();\r
- Assert.Greater(productCount, 0, "Expected non-zero product count");\r
+ AssertHelper.Greater(productCount, 0, "Expected non-zero product count");\r
}\r
\r
[Test]\r
{\r
var q = from p in db.Products select p.ProductID;\r
int productCount = q.Count();\r
- Assert.Greater(productCount, 0, "Expected non-zero product count");\r
+ AssertHelper.Greater(productCount, 0, "Expected non-zero product count");\r
Console.WriteLine();\r
}\r
[Test]\r
{\r
var q = from p in db.Products select p.ProductID;\r
int productCount = q.Count(i => i < 3);\r
- Assert.Greater(productCount, 0, "Expected non-zero product count");\r
+ AssertHelper.Greater(productCount, 0, "Expected non-zero product count");\r
Assert.IsTrue(productCount < 4, "Expected product count < 3");\r
}\r
\r
{\r
var q = from p in db.Products select p.ProductID;\r
var maxID = q.Max();\r
- Assert.Greater(maxID, 0, "Expected non-zero product count");\r
+ AssertHelper.Greater(maxID, 0, "Expected non-zero product count");\r
}\r
\r
[Test]\r
{\r
var q = from p in db.Products select p.ProductID;\r
var minID = q.Min();\r
- Assert.Greater(minID, 0, "Expected non-zero product count");\r
+ AssertHelper.Greater(minID, 0, "Expected non-zero product count");\r
}\r
\r
#if !ORACLE // picrap: this test causes an internal buffer overflow when marshaling with oracle win32 driver\r
{\r
var q = from p in db.Products select p.ProductID;\r
double avg = q.Average();\r
- Assert.Greater(avg, 0, "Expected non-zero productID average");\r
+ AssertHelper.Greater(avg, 0, "Expected non-zero productID average");\r
}\r
\r
#endif\r
var q4 = from p in db.Products select p.ProductName + p.ProductID;\r
//var q4 = from p in db.Products select p.ProductID;\r
var q5 = q4.ToList();\r
- Assert.Greater(q5.Count, 2, "Expected to see some concat strings");\r
+ AssertHelper.Greater(q5.Count, 2, "Expected to see some concat strings");\r
foreach (string s0 in q5)\r
{\r
bool startWithLetter = Char.IsLetter(s0[0]);\r
select p.ProductName+p.ProductID;\r
//var q4 = from p in db.Products select p.ProductID;\r
//var q5 = q4.ToList();\r
- Assert.Greater( q4.Count(), 2, "Expected to see some concat strings");\r
+ AssertHelper.Greater( q4.Count(), 2, "Expected to see some concat strings");\r
foreach(string s0 in q4)\r
{\r
bool startWithLetter = Char.IsLetter(s0[0]);\r
CustomerID = c.CustomerID\r
});\r
var list = q.ToList();\r
- Assert.Greater(list.Count(), 0, "Expected list");\r
- //Assert.Greater(list.Count(), 0, "Expected list");\r
+ AssertHelper.Greater(list.Count(), 0, "Expected list");\r
+ //AssertHelper.Greater(list.Count(), 0, "Expected list");\r
Assert.Ignore("test passed but: theoretically constructions of entity types are not allowed");\r
}\r
\r
//this OrderBy clause messes up the SQL statement\r
var q2 = q.OrderBy(c => c.CustomerID);\r
var list = q2.ToList();\r
- Assert.Greater(list.Count(), 0, "Expected list");\r
- //Assert.Greater(list.Count(), 0, "Expected list");\r
+ AssertHelper.Greater(list.Count(), 0, "Expected list");\r
+ //AssertHelper.Greater(list.Count(), 0, "Expected list");\r
}\r
\r
\r
orderby c.ContactName ?? ""\r
select c;\r
var list = q.ToList();\r
- Assert.Greater(list.Count(), 0, "Expected list");\r
+ AssertHelper.Greater(list.Count(), 0, "Expected list");\r
}\r
\r
[Test(Description = "Non-dynamic version of DL5_NestedObjectSelect")]\r
select new { g.Key, OrderCount = g.Count() };\r
\r
var lst = q2.ToList();\r
- Assert.Greater(lst.Count, 0, "Expected some grouped order results");\r
+ AssertHelper.Greater(lst.Count, 0, "Expected some grouped order results");\r
var result0 = lst[0];\r
Assert.IsTrue(result0.Key != null, "Key must be non-null");\r
- Assert.Greater(result0.OrderCount, 0, "Count must be > 0");\r
+ AssertHelper.Greater(result0.OrderCount, 0, "Count must be > 0");\r
//select new { g.Key , SumPerCustomer = g.Sum(o2=>o2.OrderID) };\r
}\r
\r
select new { g.Key, OrderCount = g.Count() };\r
\r
var lst = q2.ToList();\r
- Assert.Greater(lst.Count, 0, "Expected some grouped order results");\r
+ AssertHelper.Greater(lst.Count, 0, "Expected some grouped order results");\r
var result0 = lst[0];\r
Assert.IsTrue(result0.Key != null, "Key must be non-null");\r
- Assert.Greater(result0.OrderCount, 0, "Count must be > 0");\r
+ AssertHelper.Greater(result0.OrderCount, 0, "Count must be > 0");\r
//select new { g.Key , SumPerCustomer = g.Sum(o2=>o2.OrderID) };\r
}\r
\r
//where g.Count()>1\r
select new { g.Key, OrderSum = g.Sum(o => o.OrderID) };\r
var lst = q2.ToList();\r
- Assert.Greater(lst.Count, 0, "Expected some grouped order results");\r
+ AssertHelper.Greater(lst.Count, 0, "Expected some grouped order results");\r
foreach (var result in lst)\r
{\r
Console.WriteLine(" Result: custID=" + result.Key + " sum=" + result.OrderSum);\r
Assert.IsTrue(result.Key != null, "Key must be non-null");\r
- Assert.Greater(result.OrderSum, 0, "OrderSum must be > 0");\r
+ AssertHelper.Greater(result.OrderSum, 0, "OrderSum must be > 0");\r
}\r
//select new { g.Key , SumPerCustomer = g.Sum(o2=>o2.OrderID) };\r
}\r
decimal[] d = new decimal[] { 1, 4, 5, 6, 10248, 10255 };\r
var q = db.OrderDetails.Where(o => d.Contains(o.OrderID));\r
\r
- Assert.Greater(q.Count(), 0);\r
+ AssertHelper.Greater(q.Count(), 0);\r
}\r
\r
\r
\r
\r
var list = query.ToList();\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
\r
#if !DEBUG && SQLITE\r
\r
\r
var list = query.ToList();\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
\r
\r
\r
\r
var list = query.ToList();\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
\r
#if !DEBUG && (SQLITE || MSSQL)\r
\r
\r
var list = query.ToList();\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
\r
#if !DEBUG && SQLITE\r
\r
\r
var list = query.ToList();\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
\r
#if !DEBUG && SQLITE\r
\r
var list = query.ToList();\r
\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
\r
#if !DEBUG && POSTGRES\r
\r
var list = query.ToList();\r
\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
finally\r
{\r
\r
var list = query.ToList();\r
\r
- Assert.Greater(list.Count, 0);\r
+ AssertHelper.Greater(list.Count, 0);\r
}\r
finally\r
{\r
{\r
var db = CreateDB();\r
var customer = db.Customers.First();\r
- Assert.Greater(customer.Orders.Count, 0);\r
+ AssertHelper.Greater(customer.Orders.Count, 0);\r
}\r
\r
#if !DEBUG && (SQLITE || (MSSQL && !L2SQL))\r
var db = CreateDB();\r
var results = (from c in db.Customers select c.Orders).ToList();\r
\r
- Assert.Greater(results.Count, 0);\r
+ AssertHelper.Greater(results.Count, 0);\r
}\r
\r
[Test]\r
var db = CreateDB();\r
var customer = db.Customers.First();\r
\r
- Assert.Greater(customer.Orders.Count, 0, "#1");\r
+ AssertHelper.Greater(customer.Orders.Count, 0, "#1");\r
Assert.IsTrue(customer.Orders.HasLoadedOrAssignedValues, "#2");\r
customer.Orders.SetSource(System.Linq.Enumerable.Empty<Order>());\r
}\r
int ordersCount = (from cust in db.Customers\r
select cust.Orders.Count).First();\r
\r
- Assert.Greater(ordersCount, 0);\r
+ AssertHelper.Greater(ordersCount, 0);\r
\r
var customer2 = db.Customers.First();\r
customer2.Orders.SetSource(System.Linq.Enumerable.Empty<Order>());\r
var c = db.Customers.First();\r
\r
int beforeCount = c.Orders.Count;\r
- Assert.Greater(beforeCount, 0);\r
+ AssertHelper.Greater(beforeCount, 0);\r
c.Orders.Clear();\r
Assert.AreEqual(c.Orders.Count, 0);\r
c.Orders.AddRange(db.Orders);\r
- Assert.Greater(c.Orders.Count, beforeCount);\r
+ AssertHelper.Greater(c.Orders.Count, beforeCount);\r
db.Refresh(RefreshMode.OverwriteCurrentValues, c.Orders);\r
\r
Assert.AreEqual(c.Orders.Count, beforeCount);\r
var c = db.Customers.First();\r
\r
int beforeCount = c.Orders.Count;\r
- Assert.Greater(beforeCount, 0);\r
+ AssertHelper.Greater(beforeCount, 0);\r
c.Orders.Clear();\r
Assert.AreEqual(c.Orders.Count, 0);\r
c.Orders.AddRange(db.Orders);\r
\r
int middleCount = c.Orders.Count;\r
- Assert.Greater(c.Orders.Count, beforeCount);\r
+ AssertHelper.Greater(c.Orders.Count, beforeCount);\r
\r
db.Refresh(RefreshMode.KeepCurrentValues, c.Orders);\r
Assert.AreEqual(c.Orders.Count, middleCount);\r
{\r
var db = CreateDB();\r
var customer = db.Customers.Where(c => c.Orders.Count > 0).First();\r
- Assert.Greater(customer.Orders.Count, 0);\r
+ AssertHelper.Greater(customer.Orders.Count, 0);\r
bool ok;\r
System.ComponentModel.ListChangedEventArgs args = null;\r
customer.Orders.ListChanged += delegate(object sender, System.ComponentModel.ListChangedEventArgs a) \r
foreach (var c in q)\r
{\r
Assert.IsNotNull(c.CustomerID);\r
- Assert.Greater(c.OrderCount, -1);\r
+ AssertHelper.Greater(c.OrderCount, -1);\r
count++;\r
}\r
- Assert.Greater(count, 0);\r
+ AssertHelper.Greater(count, 0);\r
}\r
\r
[Test]\r
foreach (var v in q)\r
{\r
Assert.IsNotNull(v.c.CustomerID);\r
- Assert.Greater(v.OrderCount, -1);\r
+ AssertHelper.Greater(v.OrderCount, -1);\r
count++;\r
}\r
- Assert.Greater(count, 0);\r
+ AssertHelper.Greater(count, 0);\r
}\r
\r
[Test]\r
Assert.IsTrue(c.CustomerID!=null, "Non-null customerID required");\r
count++;\r
}\r
- Assert.Greater(count, 0);\r
+ AssertHelper.Greater(count, 0);\r
}\r
#endif\r
}\r
var customer = new Customer();\r
db.Customers.Attach(customer, originalCustomer);\r
\r
- Assert.Greater(db.Customers.GetModifiedMembers(customer).Count(), 0);\r
+ AssertHelper.Greater(db.Customers.GetModifiedMembers(customer).Count(), 0);\r
}\r
\r
#if !DEBUG && (SQLITE || POSTGRES || (MSSQL && !L2SQL))\r
\r
using nwind;\r
\r
-#if MONO_STRICT && !MONO\r
+#if MONO_STRICT\r
using System.Diagnostics;\r
public static class Profiler\r
{\r
newProd.QuantityPerUnit = "33 1/2";\r
db.Products.InsertOnSubmit(newProd);\r
db.SubmitChanges();\r
- Assert.Greater(newProd.ProductID, 0, "After insertion, ProductID should be non-zero");\r
+ AssertHelper.Greater(newProd.ProductID, 0, "After insertion, ProductID should be non-zero");\r
//Assert.IsFalse(newProd.IsModified, "After insertion, Product.IsModified should be false");\r
return (int)newProd.ProductID; //this test cab be used from delete tests\r
}\r
public void G2_DeleteTest()\r
{\r
int insertedID = insertProduct_priv();\r
- Assert.Greater(insertedID, 0, "DeleteTest cannot operate if row was not inserted");\r
+ AssertHelper.Greater(insertedID, 0, "DeleteTest cannot operate if row was not inserted");\r
\r
Northwind db = CreateDB();\r
\r
public void G3_DeleteTest()\r
{\r
int insertedID = insertProduct_priv();\r
- Assert.Greater(insertedID, 0, "DeleteTest cannot operate if row was not inserted");\r
+ AssertHelper.Greater(insertedID, 0, "DeleteTest cannot operate if row was not inserted");\r
\r
Northwind db = CreateDB();\r
\r
Some tests located require a connection to Oracle database to execute.
-To configure a connection, copy System.Data.OracleClient_test_default.dll.config.example
-to System.Data.OracleClient_test_default.dll.config and fill in the ConnectionString with appropriate Data Source.
+To configure a connection, set the MONO_TESTS_ORACLE_CONNECTION_STRING environment variable to a connection string like the following:
-If no System.Data.OracleClient_test_default.dll.config is present, those tests will be ignored.
+Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<host ip>)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=<sid>)));uid=<user name>;pwd=<password>;
-To test .Net 2.0 profile, copy System.Data.OracleClient_test_default.dll.config
-to System.Data.OracleClient_test_net_2_0.dll.config and launch tests with PROFILE=net_2_0 .
+If the environment variable is not present, those tests will be ignored.
Scripts for populating the database are located in Test/System.Data.OracleClient.jvm (for their usage, consult Test/System.Data.OracleClient.jvm/readme.txt).
+++ /dev/null
-<configuration>
- <appSettings>
- <add key="ConnectionString" value="Data Source=;User ID=GHTDB;Password=GHTDB;" />
- </appSettings>
-</configuration>
[TestFixtureSetUp]
public void FixtureSetUp ()
{
- connection_string = ConfigurationSettings.AppSettings.Get ("ConnectionString");
+ connection_string = Environment.GetEnvironmentVariable ("MONO_TESTS_ORACLE_CONNECTION_STRING");
if(connection_string == null)
Assert.Ignore ("Please consult README.tests.");
}
TEMPORARY TABLESPACE "TEMP" ;
GRANT CONNECT, RESOURCE, CREATE TABLE TO "GHTDB";
+ALTER USER GHTDB quota unlimited on USERS;
CREATE OR REPLACE PACKAGE "GHTDB"."GHTPKG" AS
TYPE RCT1 IS REF CURSOR;
TEMPORARY TABLESPACE "TEMP" ;
GRANT CONNECT, RESOURCE TO "GHTDB_EX";
+ALTER USER GHTDB_EX quota unlimited on USERS;
CREATE OR REPLACE PACKAGE GHTDB_EX.GHTPKG
AS
public static string ConnectionString {
get {
- string connection_string = Sys.Configuration.ConfigurationSettings.AppSettings["ConnectionString"];
+ string connection_string = Environment.GetEnvironmentVariable ("MONO_TESTS_ORACLE_CONNECTION_STRING");
if(connection_string == null)
NUnit.Framework.Assert.Ignore ("Please consult README.tests.");
return connection_string;
[SetUp]
public void SetUp()
{
- try
- {
- _ConnectionString = MonoTests.System.Data.Utils.ConnectedDataProvider.ConnectionString;
- }
- catch(Exception ex)
- {
- EndCase(ex);
- }
+ _ConnectionString = MonoTests.System.Data.Utils.ConnectedDataProvider.ConnectionString;
}
[TearDown]
To run unit test the following should be prepared:
-1. Test\System.Data.OracleClient.J2EE.config should contain an ConnectionString setting, i.e.:
-
-<?xml version="1.0" encoding="utf-8" ?>
-<configuration>
-<appSettings>
- <add key="ConnectionString" value="User ID=ghtdb;Password=ghtdb;Data Source=xp050" />
- </appSettings>
-</configuration>
-
-2. A target db should be prepared with the relevant structure, following are the instruction for each supported database.
+A target db should be prepared with the relevant structure, following are the instruction for each supported database.
in order to create the testing database, on ORACLE, run:
Run the scripts with a user wich have administrator permissions. (by default user:system, password:mainsoft).
[TestFixtureSetUp]
public void FixtureSetUp ()
{
- connection_string = ConfigurationSettings.AppSettings.Get ("ConnectionString");
+ connection_string = Environment.GetEnvironmentVariable ("MONO_TESTS_ORACLE_CONNECTION_STRING");
if(connection_string == null)
Assert.Ignore ("Please consult README.tests.");
}
[TestFixtureSetUp]
public void FixtureSetUp ()
{
- connection_string = ConfigurationSettings.AppSettings.Get ("ConnectionString");
+ connection_string = Environment.GetEnvironmentVariable ("MONO_TESTS_ORACLE_CONNECTION_STRING");
}
[SetUp]
TEST_LIB_REFS = System.Core Mono.Data.Sqlite
TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) -nowarn:618,169,612,219,168
+TEST_NUNITLITE_APP_CONFIG_GLOBAL=Test/test-config-file
+
TEST_MONO_PATH = .
EXTRA_DISTFILES = \
$(wildcard Test/System.Xml/*.xml) \
$(wildcard Test/System.Xml/*.xsd) \
$(wildcard Test/System.Data/schemas/*.xsd) \
- app_test_net_4_x.config \
+ Test/test-config-file \
Test/System.Data/binserialize/*.bin \
SqliteTest.db \
referencesource.sources
sed -e s/PARAMETEROBJECTNAME/SqlParameter/g >$@
include ../../build/library.make
-
-$(test_lib): $(test_lib).config
-
-$(test_lib).config: app_test_$(PROFILE).config
- cp $< $@
if (Client.Available <= 0)
return -1; // Error
- IPEndPoint endpoint = CreateLocalEndpoint ();
- if (endpoint == null)
- return -1;
+ IPEndPoint remoteEndpoint;
+ switch (Client.AddressFamily) {
+ case AddressFamily.InterNetwork:
+ remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);
+ break;
+ case AddressFamily.InterNetworkV6:
+ remoteEndpoint = new IPEndPoint(IPAddress.IPv6Any, 0);
+ break;
+ default:
+ return -1; // Error
+ }
Byte [] rawrs;
- rawrs = Receive (ref endpoint);
+ rawrs = Receive (ref remoteEndpoint);
string rs = Encoding.ASCII.GetString (rawrs);
return SqlServerTcpPort;
}
-
- IPEndPoint CreateLocalEndpoint ()
- {
- foreach (var addr in Dns.GetHostEntry ("localhost").AddressList) {
- if (addr.AddressFamily == Client.AddressFamily)
- return new IPEndPoint (addr, 0);
- }
-
- return null;
- }
}
struct ColumnInfo
using NUnit.Framework;
using System;
using System.Data;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Data
{
using NUnit.Framework;
using System;
using System.Data;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Data
{
using NUnit.Framework;
using System;
using System.Data;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Data
{
using NUnit.Framework;\r
using System;\r
using System.Data;\r
-#if !MOBILE\r
-using NUnit.Framework.SyntaxHelpers;\r
-#endif\r
\r
namespace MonoTests.System.Data\r
{\r
namespace MonoTests.System.Data
{
[TestFixture]
- public class TypedDataSetGeneratorTest : Assertion
+ public class TypedDataSetGeneratorTest
{
private ICodeGenerator gen;
private ICodeCompiler compiler;
public void TestGenerateIdName ()
{
- AssertEquals ("#1", "a", TypedDataSetGenerator.GenerateIdName ("a", gen));
- AssertEquals ("#2", "_int", TypedDataSetGenerator.GenerateIdName ("int", gen));
- AssertEquals ("#3", "_", TypedDataSetGenerator.GenerateIdName ("_", gen));
- AssertEquals ("#3-2", "_", TypedDataSetGenerator.GenerateIdName ("_", gen));
- AssertEquals ("#4", "_1", TypedDataSetGenerator.GenerateIdName ("1", gen));
- AssertEquals ("#4-2", "_1", TypedDataSetGenerator.GenerateIdName ("1", gen));
- AssertEquals ("#5", "_1a", TypedDataSetGenerator.GenerateIdName ("1a", gen));
- AssertEquals ("#6", "_1_2", TypedDataSetGenerator.GenerateIdName ("1*2", gen));
- AssertEquals ("#7", "__", TypedDataSetGenerator.GenerateIdName ("-", gen));
- AssertEquals ("#8", "__", TypedDataSetGenerator.GenerateIdName ("+", gen));
- AssertEquals ("#9", "_", TypedDataSetGenerator.GenerateIdName ("", gen));
- AssertEquals ("#10", "___", TypedDataSetGenerator.GenerateIdName ("--", gen));
- AssertEquals ("#11", "___", TypedDataSetGenerator.GenerateIdName ("++", gen));
- AssertEquals ("#12", "\u3042", TypedDataSetGenerator.GenerateIdName ("\u3042", gen));
+ Assert.AreEqual ("a", TypedDataSetGenerator.GenerateIdName ("a", gen), "#1");
+ Assert.AreEqual ("_int", TypedDataSetGenerator.GenerateIdName ("int", gen), "#2");
+ Assert.AreEqual ("_", TypedDataSetGenerator.GenerateIdName ("_", gen), "#3");
+ Assert.AreEqual ("_", TypedDataSetGenerator.GenerateIdName ("_", gen), "#3-2");
+ Assert.AreEqual ("_1", TypedDataSetGenerator.GenerateIdName ("1", gen), "#4");
+ Assert.AreEqual ("_1", TypedDataSetGenerator.GenerateIdName ("1", gen), "#4-2");
+ Assert.AreEqual ("_1a", TypedDataSetGenerator.GenerateIdName ("1a", gen), "#5");
+ Assert.AreEqual ("_1_2", TypedDataSetGenerator.GenerateIdName ("1*2", gen), "#6");
+ Assert.AreEqual ("__", TypedDataSetGenerator.GenerateIdName ("-", gen), "#7");
+ Assert.AreEqual ("__", TypedDataSetGenerator.GenerateIdName ("+", gen), "#8");
+ Assert.AreEqual ("_", TypedDataSetGenerator.GenerateIdName ("", gen), "#9");
+ Assert.AreEqual ("___", TypedDataSetGenerator.GenerateIdName ("--", gen), "#10");
+ Assert.AreEqual ("___", TypedDataSetGenerator.GenerateIdName ("++", gen), "#11");
+ Assert.AreEqual ("\u3042", TypedDataSetGenerator.GenerateIdName ("\u3042", gen), "#12");
}
[Test]
ccu.Namespaces.Add (cns);
CompilerResults r = compiler.CompileAssemblyFromDom (
new CompilerParameters (), ccu);
- AssertEquals (0, r.Errors.Count);
+ Assert.AreEqual (0, r.Errors.Count);
}
}
}
using NUnit.Framework;
using System;
using System.Data;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Data
{
--- /dev/null
+ <configSections>
+ <section name="system.data_test"
+ type="System.Data.Common.DbProviderFactoriesConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
+ <section name="connectionStrings_test"
+ type="System.Configuration.ConnectionStringsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
+ </configSections>
+ <system.data>
+ <DbProviderFactories>
+ <add name="ProviderTest2.Name"
+ invariant="ProviderTest2.InvariantName"
+ support="FF"
+ description="ProviderTest2.Description"
+ type="ProviderTest2.AssemblyQualifiedName"/>
+ </DbProviderFactories>
+ </system.data>
+ <system.data_test>
+ <DbProviderFactories>
+ <add name="ProviderTest3.Name"
+ invariant="ProviderTest3.InvariantName"
+ support="FF"
+ description="ProviderTest3.Description"
+ type="ProviderTest3.AssemblyQualifiedName"/>
+ <clear />
+ <add name="ProviderTest4.Name"
+ invariant="ProviderTest4.InvariantName"
+ support="FF"
+ description="ProviderTest4.Description"
+ type="ProviderTest4.AssemblyQualifiedName"/>
+ <add name="ProviderTest5.Name"
+ invariant="ProviderTest5.InvariantName"
+ support="FF"
+ description="ProviderTest5.Description"
+ type="ProviderTest5.AssemblyQualifiedName"/>
+ <remove invariant="ProviderTest5.InvariantName" />
+ <add name="ProviderTest.Name"
+ invariant="ProviderTest.InvariantName"
+ support="FF"
+ description="ProviderTest.Description"
+ type="ProviderTest.AssemblyQualifiedName"/>
+ </DbProviderFactories>
+ </system.data_test>
+ <connectionStrings_test>
+ <add name="Publications" providerName="System.Data.SqlClient"
+ connectionString="Data Source=MyServer;Initial Catalog=pubs;integrated security=SSPI" />
+ </connectionStrings_test>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <configSections>
- <section name="system.data_test"
- type="System.Data.Common.DbProviderFactoriesConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
- <section name="connectionStrings_test"
- type="System.Configuration.ConnectionStringsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
- </configSections>
- <system.data>
- <DbProviderFactories>
- <add name="ProviderTest2.Name"
- invariant="ProviderTest2.InvariantName"
- support="FF"
- description="ProviderTest2.Description"
- type="ProviderTest2.AssemblyQualifiedName"/>
- </DbProviderFactories>
- </system.data>
- <system.data_test>
- <DbProviderFactories>
- <add name="ProviderTest3.Name"
- invariant="ProviderTest3.InvariantName"
- support="FF"
- description="ProviderTest3.Description"
- type="ProviderTest3.AssemblyQualifiedName"/>
- <clear />
- <add name="ProviderTest4.Name"
- invariant="ProviderTest4.InvariantName"
- support="FF"
- description="ProviderTest4.Description"
- type="ProviderTest4.AssemblyQualifiedName"/>
- <add name="ProviderTest5.Name"
- invariant="ProviderTest5.InvariantName"
- support="FF"
- description="ProviderTest5.Description"
- type="ProviderTest5.AssemblyQualifiedName"/>
- <remove invariant="ProviderTest5.InvariantName" />
- <add name="ProviderTest.Name"
- invariant="ProviderTest.InvariantName"
- support="FF"
- description="ProviderTest.Description"
- type="ProviderTest.AssemblyQualifiedName"/>
- </DbProviderFactories>
- </system.data_test>
- <connectionStrings_test>
- <add name="Publications" providerName="System.Data.SqlClient"
- connectionString="Data Source=MyServer;Initial Catalog=pubs;integrated security=SSPI" />
- </connectionStrings_test>
-</configuration>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <configSections>
- <section name="system.data_test"
- type="System.Data.Common.DbProviderFactoriesConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
- <section name="connectionStrings_test"
- type="System.Configuration.ConnectionStringsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
- </configSections>
- <system.data>
- <DbProviderFactories>
- <add name="ProviderTest2.Name"
- invariant="ProviderTest2.InvariantName"
- support="FF"
- description="ProviderTest2.Description"
- type="ProviderTest2.AssemblyQualifiedName"/>
- </DbProviderFactories>
- </system.data>
- <system.data_test>
- <DbProviderFactories>
- <add name="ProviderTest3.Name"
- invariant="ProviderTest3.InvariantName"
- support="FF"
- description="ProviderTest3.Description"
- type="ProviderTest3.AssemblyQualifiedName"/>
- <clear />
- <add name="ProviderTest4.Name"
- invariant="ProviderTest4.InvariantName"
- support="FF"
- description="ProviderTest4.Description"
- type="ProviderTest4.AssemblyQualifiedName"/>
- <add name="ProviderTest5.Name"
- invariant="ProviderTest5.InvariantName"
- support="FF"
- description="ProviderTest5.Description"
- type="ProviderTest5.AssemblyQualifiedName"/>
- <remove invariant="ProviderTest5.InvariantName" />
- <add name="ProviderTest.Name"
- invariant="ProviderTest.InvariantName"
- support="FF"
- description="ProviderTest.Description"
- type="ProviderTest.AssemblyQualifiedName"/>
- </DbProviderFactories>
- </system.data_test>
- <connectionStrings_test>
- <add name="Publications" providerName="System.Data.SqlClient"
- connectionString="Data Source=MyServer;Initial Catalog=pubs;integrated security=SSPI" />
- </connectionStrings_test>
-</configuration>
+../../test-helpers/NunitHelpers.cs
../../../build/common/Locale.cs
../System.Drawing/gdipEnums.cs
../System.Drawing/gdipFunctions.cs
using System.Drawing.Imaging;\r
using DrawingTestHelper;\r
using System.IO;\r
-#if !MONOTOUCH\r
-using NUnit.Framework.SyntaxHelpers;\r
-#endif\r
\r
namespace Test.Sys.Drawing.GraphicsFixtures {\r
#region GraphicsFixtureProps\r
public void StartListening(object data)
{
- serverChannel.StartListening(data);
+ if (serverChannel != null)
+ serverChannel.StartListening(data);
}
public object ChannelData
public void StopListening(object data)
{
- serverChannel.StopListening(data);
+ if (serverChannel != null)
+ serverChannel.StopListening(data);
}
public string[] GetUrlsForUri(string objectURI)
+../../test-helpers/NunitHelpers.cs
System.Runtime.Remoting.Channels.Tcp/TcpChannelTest.cs
ServerObject.cs
ContextsTest.cs
public void Main ()
{
channel = new HttpChannel (0);
- try {
ChannelServices.RegisterChannel (channel);
MarshalByRefObject obj = (MarshalByRefObject) RemotingServices.Connect (
typeof (IFactorial),
"http://localhost:60000/MyEndPoint");
IFactorial cal = (IFactorial) obj;
- Assert.AreEqual (cal.CalculateFactorial (4), 24);
- } finally {
- ChannelServices.UnregisterChannel (channel);
- }
+ Assert.AreEqual (cal.CalculateFactorial (4), 24);
}
[TestFixtureSetUp]
IpcServerChannel chan = new IpcServerChannel (channelName, portName);
string[] uris = chan.GetUrlsForUri ("server.rem");
Assert.IsNotNull (uris);
- Assert.Greater (uris.Length, 0);
+ AssertHelper.Greater (uris.Length, 0);
bool found = false;
foreach (string s in uris) {
IpcChannel chan = new IpcChannel (props, null, null);
string[] uris = chan.GetUrlsForUri ("server.rem");
Assert.IsNotNull (uris);
- Assert.Greater (uris.Length, 0);
+ AssertHelper.Greater (uris.Length, 0);
bool found = false;
foreach (string s in uris) {
\r
// The main test class\r
[TestFixture]\r
- public class RemotingServicesTest : Assertion\r
+ public class RemotingServicesTest\r
{\r
private static int MarshalObjectId = 0;\r
\r
MarshalObject objMarshal = NewMarshalObject ();\r
ObjRef objRef = RemotingServices.Marshal (objMarshal);\r
\r
- Assert ("#A01", objRef.URI != null);\r
+ Assert.IsNotNull (objRef.URI, "#A01");\r
\r
MarshalObject objRem = (MarshalObject) RemotingServices.Unmarshal (objRef);\r
- AssertEquals ("#A02", objMarshal.Id, objRem.Id);\r
+ Assert.AreEqual (objMarshal.Id, objRem.Id, "#A02");\r
\r
objRem.Id = 2;\r
- AssertEquals ("#A03", objMarshal.Id, objRem.Id);\r
+ Assert.AreEqual (objMarshal.Id, objRem.Id, "#A03");\r
\r
// TODO: uncomment when RemotingServices.Disconnect is implemented\r
//RemotingServices.Disconnect(objMarshal);\r
\r
objRef = RemotingServices.Marshal (objMarshal, objMarshal.Uri);\r
\r
- Assert ("#A04", objRef.URI.EndsWith (objMarshal.Uri));\r
+ Assert.IsTrue (objRef.URI.EndsWith (objMarshal.Uri), "#A04");\r
// TODO: uncomment when RemotingServices.Disconnect is implemented\r
//RemotingServices.Disconnect(objMarshal);\r
}\r
ObjRef objRef = RemotingServices.Marshal (derivedObjMarshal, derivedObjMarshal.Uri, typeof (MarshalObject));\r
\r
// Check that the type of the marshaled object is MarshalObject\r
- Assert ("#A05", objRef.TypeInfo.TypeName.StartsWith ((typeof (MarshalObject)).ToString ()));\r
+ Assert.IsTrue (objRef.TypeInfo.TypeName.StartsWith ((typeof (MarshalObject)).ToString ()), "#A05");\r
\r
// TODO: uncomment when RemotingServices.Disconnect is implemented\r
//RemotingServices.Disconnect(derivedObjMarshal);\r
{\r
MarshalObject objMarshal = NewMarshalObject ();\r
\r
- Assert ("#A06", RemotingServices.GetObjectUri (objMarshal) == null);\r
+ Assert.IsNull (RemotingServices.GetObjectUri (objMarshal), "#A06");\r
\r
RemotingServices.Marshal (objMarshal);\r
\r
- Assert ("#A07", RemotingServices.GetObjectUri (objMarshal) != null);\r
+ Assert.IsNotNull (RemotingServices.GetObjectUri (objMarshal), "#A07");\r
// TODO: uncomment when RemotingServices.Disconnect is implemented\r
//RemotingServices.Disconnect(objMarshal);\r
}\r
try {\r
RemotingServices.Marshal (objMarshal, objMarshal.Uri);\r
MarshalObject objRem = (MarshalObject) RemotingServices.Connect (typeof (MarshalObject), "tcp://localhost:1236/" + objMarshal.Uri);\r
- Assert ("#A08", RemotingServices.IsTransparentProxy (objRem));\r
+ Assert.IsTrue (RemotingServices.IsTransparentProxy (objRem), "#A08");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
RemotingServices.Disconnect (objMarshal);\r
// a real object\r
try {\r
RemotingServices.Marshal (objRem, objMarshal.Uri);\r
- Fail ("#1");\r
+ Assert.Fail ("#1");\r
} catch (RemotingException e) {\r
}\r
} finally {\r
objRem.Method1 ();\r
\r
// Tests RemotingServices.GetMethodBaseFromMethodMessage()\r
- AssertEquals ("#A09", "Method1", proxy.MthBase.Name);\r
- Assert ("#A09.1", !proxy.IsMethodOverloaded);\r
+ Assert.AreEqual ("Method1", proxy.MthBase.Name, "#A09");\r
+ Assert.IsFalse (proxy.IsMethodOverloaded, "#A09.1");\r
\r
objRem.Method2 ();\r
- Assert ("#A09.2", proxy.IsMethodOverloaded);\r
+ Assert.IsTrue (proxy.IsMethodOverloaded, "#A09.2");\r
\r
// Tests RemotingServices.ExecuteMessage();\r
// If ExecuteMessage does it job well, Method1 should be called 2 times\r
- AssertEquals ("#A10", 2, MarshalObject.Called);\r
+ Assert.AreEqual (2, MarshalObject.Called, "#A10");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
\r
MarshalObject objRem = (MarshalObject) Activator.GetObject (typeof (MarshalObject), "tcp://localhost:1238/MarshalObject.rem");\r
\r
- Assert ("#A10.1", RemotingServices.IsTransparentProxy (objRem));\r
+ Assert.IsTrue (RemotingServices.IsTransparentProxy (objRem), "#A10.1");\r
\r
objRem.Method1 ();\r
Thread.Sleep (20);\r
- Assert ("#A10.2", !MarshalObject.IsMethodOneWay);\r
+ Assert.IsFalse (MarshalObject.IsMethodOneWay, "#A10.2");\r
objRem.Method3 ();\r
Thread.Sleep (20);\r
- Assert ("#A10.3", MarshalObject.IsMethodOneWay);\r
+ Assert.IsTrue (MarshalObject.IsMethodOneWay, "#A10.3");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
\r
ObjRef objRefRem = RemotingServices.GetObjRefForProxy ((MarshalByRefObject) objRem);\r
\r
- Assert ("#A11", objRefRem != null);\r
+ Assert.IsNotNull (objRefRem, "#A11");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
\r
RealProxy rp = RemotingServices.GetRealProxy (objRem);\r
\r
- Assert ("#A12", rp != null);\r
- AssertEquals ("#A13", "MonoTests.System.Runtime.Remoting.RemotingServicesInternal.MyProxy", rp.GetType ().ToString ());\r
+ Assert.IsNotNull (rp, "#A12");\r
+ Assert.AreEqual ("MonoTests.System.Runtime.Remoting.RemotingServicesInternal.MyProxy", rp.GetType ().ToString (), "#A13");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
RemotingServices.Marshal (objRem);\r
\r
objRem = (MarshalObject) Activator.GetObject (typeof (MarshalObject), "tcp://localhost:1242/" + objRem.Uri);\r
- Assert ("#A14", objRem != null);\r
+ Assert.IsNotNull (objRem, "#A14");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
RemotingServices.Marshal (objRem);\r
\r
Type typeRem = RemotingServices.GetServerTypeForUri (RemotingServices.GetObjectUri (objRem));\r
- AssertEquals ("#A15", type, typeRem);\r
+ Assert.AreEqual (type, typeRem, "#A15");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
\r
MarshalObject objRem = (MarshalObject) Activator.GetObject (typeof (MarshalObject), "tcp://localhost:1245/MarshalObject2.rem");\r
\r
- Assert ("#A16", RemotingServices.IsObjectOutOfAppDomain (objRem));\r
- Assert ("#A17", RemotingServices.IsObjectOutOfContext (objRem));\r
+ Assert.IsTrue (RemotingServices.IsObjectOutOfAppDomain (objRem), "#A16");\r
+ Assert.IsTrue (RemotingServices.IsObjectOutOfContext (objRem), "#A17");\r
\r
MarshalObject objMarshal = new MarshalObject ();\r
- Assert ("#A18", !RemotingServices.IsObjectOutOfAppDomain (objMarshal));\r
- Assert ("#A19", !RemotingServices.IsObjectOutOfContext (objMarshal));\r
+ Assert.IsFalse (RemotingServices.IsObjectOutOfAppDomain (objMarshal), "#A18");\r
+ Assert.IsFalse (RemotingServices.IsObjectOutOfContext (objMarshal), "#A19");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
MarshalObject objRem = (MarshalObject) Activator.GetObject (typeof (MarshalObject), "tcp://localhost:1246/app/obj3.rem");\r
MarshalObject objRem2 = (MarshalObject) Activator.GetObject (typeof (MarshalObject), "tcp://localhost:1246/obj3.rem");\r
\r
- Assert ("#AN1", RemotingServices.IsTransparentProxy (objRem));\r
- Assert ("#AN2", RemotingServices.IsTransparentProxy (objRem2));\r
+ Assert.IsTrue (RemotingServices.IsTransparentProxy (objRem), "#AN1");\r
+ Assert.IsTrue (RemotingServices.IsTransparentProxy (objRem2), "#AN2");\r
\r
- AssertNotNull ("#AN3", RemotingServices.GetServerTypeForUri ("obj3.rem"));\r
- AssertNotNull ("#AN4", RemotingServices.GetServerTypeForUri ("/app/obj3.rem"));\r
- AssertNull ("#AN5", RemotingServices.GetServerTypeForUri ("//app/obj3.rem"));\r
- AssertNull ("#AN6", RemotingServices.GetServerTypeForUri ("app/obj3.rem"));\r
- AssertNull ("#AN7", RemotingServices.GetServerTypeForUri ("/whatever/obj3.rem"));\r
- AssertNotNull ("#AN8", RemotingServices.GetServerTypeForUri ("/obj3.rem"));\r
- AssertNull ("#AN9", RemotingServices.GetServerTypeForUri ("//obj3.rem"));\r
+ Assert.IsNotNull (RemotingServices.GetServerTypeForUri ("obj3.rem"), "#AN3");\r
+ Assert.IsNotNull (RemotingServices.GetServerTypeForUri ("/app/obj3.rem"), "#AN4");\r
+ Assert.IsNull (RemotingServices.GetServerTypeForUri ("//app/obj3.rem"), "#AN5");\r
+ Assert.IsNull (RemotingServices.GetServerTypeForUri ("app/obj3.rem"), "#AN6");\r
+ Assert.IsNull (RemotingServices.GetServerTypeForUri ("/whatever/obj3.rem"), "#AN7");\r
+ Assert.IsNotNull (RemotingServices.GetServerTypeForUri ("/obj3.rem"), "#AN8");\r
+ Assert.IsNull (RemotingServices.GetServerTypeForUri ("//obj3.rem"), "#AN9");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
RemotingConfiguration.RegisterWellKnownServiceType (typeof (MarshalObject), "getobjectwithchanneldata.rem", WellKnownObjectMode.Singleton);\r
\r
string channelData = "test";\r
- AssertNotNull ("#01", Activator.GetObject (typeof (MarshalObject), "tcp://localhost:1247/getobjectwithchanneldata.rem", channelData));\r
+ Assert.IsNotNull (Activator.GetObject (typeof (MarshalObject), "tcp://localhost:1247/getobjectwithchanneldata.rem", channelData), "#01");\r
} finally {\r
ChannelServices.UnregisterChannel (chn);\r
}\r
RemotingConfiguration.Configure (null);\r
\r
o = RemotingServices.Connect (typeof (MarshalByRefObject), "tcp://localhost:3434/ff1.rem");\r
- Assert ("#m1", o is DD);\r
- Assert ("#m2", o is A);\r
- Assert ("#m3", o is B);\r
- Assert ("#m4", !(o is CC));\r
+ Assert.IsInstanceOfType (typeof (DD), o, "#m1");\r
+ Assert.IsInstanceOfType (typeof (A), o, "#m2");\r
+ Assert.IsInstanceOfType (typeof (B), o, "#m3");\r
+ AssertHelper.IsNotInstanceOfType (typeof (CC), !(o is CC), "#m4");\r
\r
o = RemotingServices.Connect (typeof (A), "tcp://localhost:3434/ff3.rem");\r
- Assert ("#a1", o is DD);\r
- Assert ("#a2", o is A);\r
- Assert ("#a3", o is B);\r
- Assert ("#a4", !(o is CC));\r
+ Assert.IsInstanceOfType (typeof (DD), o, "#a1");\r
+ Assert.IsInstanceOfType (typeof (A), o, "#a2");\r
+ Assert.IsInstanceOfType (typeof (B), o, "#a3");\r
+ AssertHelper.IsNotInstanceOfType (typeof (CC), o, "#a4");\r
\r
o = RemotingServices.Connect (typeof (DD), "tcp://localhost:3434/ff4.rem");\r
- Assert ("#d1", o is DD);\r
- Assert ("#d2", o is A);\r
- Assert ("#d3", o is B);\r
- Assert ("#d4", !(o is CC));\r
+ Assert.IsInstanceOfType (typeof (DD), o, "#d1");\r
+ Assert.IsInstanceOfType (typeof (A), o, "#d2");\r
+ Assert.IsInstanceOfType (typeof (B), o, "#d3");\r
+ AssertHelper.IsNotInstanceOfType (typeof (CC), o, "#d4");\r
\r
o = RemotingServices.Connect (typeof (CC), "tcp://localhost:3434/ff5.rem");\r
- Assert ("#c1", !(o is DD));\r
- Assert ("#c2", o is A);\r
- Assert ("#c3", o is B);\r
- Assert ("#c4", o is CC);\r
+ AssertHelper.IsNotInstanceOfType (typeof (DD), o, "#c1");\r
+ Assert.IsInstanceOfType (typeof (A), o, "#c2");\r
+ Assert.IsInstanceOfType (typeof (B), o, "#c3");\r
+ Assert.IsInstanceOfType (typeof (CC), o, "#c4");\r
}\r
// Don't add any tests that must create channels\r
// after ConnectProxyCast (), because this test calls\r
using System.ServiceModel;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Runtime.Serialization
{
using Microsoft.CSharp;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
using QName = System.Xml.XmlQualifiedName;
var type = exporter.Schemas.GlobalTypes [typeName];
Assert.That (type, Is.Not.Null, "#2");
- Assert.That (type, Is.InstanceOfType (typeof (XmlSchemaComplexType)), "#3");
+ Assert.IsInstanceOfType (typeof (XmlSchemaComplexType), type, "#3");
var complex = (XmlSchemaComplexType)type;
Assert.That (complex.Annotation, Is.Null, "#4");
Assert.That (list, Is.Not.Null, "#6");
Assert.That (list.Annotation, Is.Null, "#6a");
Assert.That (list.Name, Is.EqualTo ("list"), "#6b");
- Assert.That (list.ElementSchemaType, Is.InstanceOfType (typeof (XmlSchemaComplexType)), "#6c");
+ Assert.IsInstanceOfType (typeof (XmlSchemaComplexType), list.ElementSchemaType, "#6c");
var listElement = (XmlSchemaComplexType)list.ElementSchemaType;
Assert.That (listElement.QualifiedName.Namespace, Is.EqualTo (MSArraysNamespace), "#6d");
Assert.That (listElement.QualifiedName.Name, Is.EqualTo ("ArrayOfint"), "#6e");
- Assert.That (listElement.Particle, Is.InstanceOfType (typeof(XmlSchemaSequence)), "#7");
+ Assert.IsInstanceOfType (typeof(XmlSchemaSequence), listElement.Particle, "#7");
var listSeq = (XmlSchemaSequence)listElement.Particle;
Assert.That (listSeq.Items.Count, Is.EqualTo (1), "#7b");
- Assert.That (listSeq.Items[0], Is.InstanceOfType (typeof(XmlSchemaElement)), "#7c");
+ Assert.IsInstanceOfType (typeof(XmlSchemaElement), listSeq.Items[0], "#7c");
Assert.That (listSeq.Annotation, Is.Null, "#7d");
var listSeqElement = (XmlSchemaElement)listSeq.Items[0];
Assert.That (dict, Is.Not.Null, "#8");
Assert.That (dict.Annotation, Is.Null, "#8a");
Assert.That (dict.Name, Is.EqualTo ("dictionary"), "#8b");
- Assert.That (dict.ElementSchemaType, Is.InstanceOfType (typeof (XmlSchemaComplexType)), "#8c");
+ Assert.IsInstanceOfType (typeof (XmlSchemaComplexType), dict.ElementSchemaType, "#8c");
var dictElement = (XmlSchemaComplexType)dict.ElementSchemaType;
Assert.That (dictElement.QualifiedName.Namespace, Is.EqualTo (MSArraysNamespace), "#8d");
Assert.That (dictElement.QualifiedName.Name, Is.EqualTo ("ArrayOfKeyValueOfstringdouble"), "#8e");
- Assert.That (dictElement.Particle, Is.InstanceOfType (typeof(XmlSchemaSequence)), "#9");
+ Assert.IsInstanceOfType (typeof(XmlSchemaSequence), dictElement.Particle, "#9");
var dictSeq = (XmlSchemaSequence)dictElement.Particle;
Assert.That (dictSeq.Items.Count, Is.EqualTo (1), "#9b");
- Assert.That (dictSeq.Items[0], Is.InstanceOfType (typeof(XmlSchemaElement)), "#9c");
+ Assert.IsInstanceOfType (typeof(XmlSchemaElement), dictSeq.Items[0], "#9c");
Assert.That (dictSeq.Annotation, Is.Null, "#9d");
var dictSeqElement = (XmlSchemaElement)dictSeq.Items[0];
Assert.That (custom, Is.Not.Null, "#10");
Assert.That (custom.Annotation, Is.Null, "#10a");
Assert.That (custom.Name, Is.EqualTo ("customCollection"), "#10b");
- Assert.That (custom.ElementSchemaType, Is.InstanceOfType (typeof (XmlSchemaComplexType)), "#10c");
+ Assert.IsInstanceOfType (typeof (XmlSchemaComplexType), custom.ElementSchemaType, "#10c");
var customElement = (XmlSchemaComplexType)custom.ElementSchemaType;
var customEQN = customElement.QualifiedName;
Assert.That (customEQN.Name.StartsWith ("XsdDataContractExporterTest2.MyCollectionOfstring", StringComparison.InvariantCultureIgnoreCase),
Is.True, "#10e");
- Assert.That (customElement.Particle, Is.InstanceOfType (typeof(XmlSchemaSequence)), "#11");
+ Assert.IsInstanceOfType (typeof(XmlSchemaSequence), customElement.Particle, "#11");
var customSeq = (XmlSchemaSequence)customElement.Particle;
Assert.That (customSeq.Items.Count, Is.EqualTo (1), "#11b");
- Assert.That (customSeq.Items[0], Is.InstanceOfType (typeof(XmlSchemaElement)), "#11c");
+ Assert.IsInstanceOfType (typeof(XmlSchemaElement), customSeq.Items[0], "#11c");
Assert.That (customSeq.Annotation, Is.Null, "#11d");
var customSeqElement = (XmlSchemaElement)customSeq.Items[0];
using Microsoft.CSharp;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
using QName = System.Xml.XmlQualifiedName;
{
FaultCode fc = null;
FaultReason fr = null;
- object details = null;
+ string actor = null;
XmlDictionaryReader r = message.GetReaderAtBodyContents ();
r.ReadStartElement ("Fault", message.Version.Envelope.Namespace);
r.MoveToContent ();
case "faultstring":
fr = new FaultReason (r.ReadElementContentAsString());
break;
- case "detail":
- return new XmlReaderDetailMessageFault (message, r, fc, fr, null, null);
case "faultactor":
+ actor = r.ReadElementContentAsString();
+ break;
+ case "detail":
+ return new XmlReaderDetailMessageFault (message, r, fc, fr, actor, null);
default:
- throw new NotImplementedException ();
+ throw new XmlException (String.Format ("Unexpected node {0} name {1}", r.NodeType, r.Name));
}
r.MoveToContent ();
}
if (fr == null)
throw new XmlException ("Reason is missing in the Fault message");
- if (details == null)
- return CreateFault (fc, fr);
- return CreateFault (fc, fr, details);
+ return new SimpleMessageFault (fc, fr, false, null, null, actor, null);
}
static MessageFault CreateFault12 (Message message, int maxBufferSize)
public void Start ()
{
- if (loop_thread == null)
+ if (loop_thread == null) {
loop_thread = new Thread (new ThreadStart (Loop));
+ loop_thread.IsBackground = true;
+ }
+
loop_thread.Start ();
}
Logger.Warning (String.Format ("Channel listener '{0}' is not closed. Aborting.", owner.Listener.GetType ()));
owner.Listener.Abort ();
}
- if (loop_thread != null && loop_thread.IsAlive)
- loop_thread.Abort ();
+ if (loop_thread != null && loop_thread.IsAlive) {
+ if (!loop_thread.Join (500))
+ loop_thread.Abort ();
+ }
loop_thread = null;
}
+../../test-helpers/NunitHelpers.cs
NUnitMoonHelper.cs
FeatureBased/Features.Client/AsyncCallTesterProxy.cs
FeatureBased/Features.Client/AsyncPatternServer.cs
using System.ServiceModel.Description;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
using QName = System.Xml.XmlQualifiedName;
using WS = System.Web.Services.Description;
static void CheckSoapBinding (object extension, string transport, TestLabel label)
{
label.EnterScope ("soap");
- Assert.That (extension, Is.InstanceOfType (typeof (WS.SoapBinding)), label.Get ());
+ Assert.That (extension, Is.AssignableTo<WS.SoapBinding>(), label.Get ());
var soap = (WS.SoapBinding)extension;
Assert.That (soap.Style, Is.EqualTo (WS.SoapBindingStyle.Document), label.Get ());
Assert.That (soap.Transport, Is.EqualTo (transport), label.Get ());
label.EnterScope ("http");
if (security == BasicHttpSecurityMode.Message) {
- Assert.That (binding, Is.InstanceOfType (typeof(CustomBinding)), label.Get ());
+ Assert.IsInstanceOfType (typeof(CustomBinding), binding, label.Get ());
} else {
- Assert.That (binding, Is.InstanceOfType (typeof(BasicHttpBinding)), label.Get ());
+ Assert.IsInstanceOfType (typeof(BasicHttpBinding), binding, label.Get ());
var basicHttp = (BasicHttpBinding)binding;
Assert.That (basicHttp.EnvelopeVersion, Is.EqualTo (EnvelopeVersion.Soap11), label.Get ());
Assert.That (basicHttp.MessageVersion, Is.EqualTo (MessageVersion.Soap11), label.Get ());
label.EnterScope ("text");
if (encoding == WSMessageEncoding.Text) {
Assert.That (textElement, Is.Not.Null, label.Get ());
- Assert.That (textElement.WriteEncoding, Is.InstanceOfType (typeof(UTF8Encoding)), label.Get ());
+ Assert.IsInstanceOfType (typeof(UTF8Encoding), textElement.WriteEncoding, label.Get ());
} else {
Assert.That (textElement, Is.Null, label.Get ());
}
{
label.EnterScope ("net-tcp");
if (security == SecurityMode.Message) {
- Assert.That (binding, Is.InstanceOfType (typeof(CustomBinding)), label.Get ());
+ Assert.IsInstanceOfType (typeof(CustomBinding), binding, label.Get ());
} else {
- Assert.That (binding, Is.InstanceOfType (typeof(NetTcpBinding)), label.Get ());
+ Assert.IsInstanceOfType (typeof(NetTcpBinding), binding, label.Get ());
var netTcp = (NetTcpBinding)binding;
Assert.That (netTcp.EnvelopeVersion, Is.EqualTo (EnvelopeVersion.Soap12), label.Get ());
Assert.That (netTcp.MessageVersion, Is.EqualTo (MessageVersion.Soap12WSAddressing10), label.Get ());
foreach (var node in all.ChildNodes) {
if (node is XmlWhitespace)
continue;
- Assert.That (node, Is.InstanceOfType (typeof (XmlElement)), label.ToString ());
+ Assert.IsInstanceOfType (typeof (XmlElement), node, label.ToString ());
collection.Add ((XmlElement)node);
}
label.LeaveScope ();
label.EnterScope ("extensions");
Assert.That (op.Extensions, Is.Not.Null, label.Get ());
Assert.That (op.Extensions.Count, Is.EqualTo (1), label.Get ());
- Assert.That (op.Extensions [0], Is.InstanceOfType (typeof (WS.SoapOperationBinding)), label.Get ());
+ Assert.That (op.Extensions [0], Is.AssignableTo<WS.SoapOperationBinding>(), label.Get ());
var soap = (WS.SoapOperationBinding)op.Extensions [0];
TestSoap (soap, soap12, label);
label.LeaveScope ();
Assert.That (binding.ExtensibleAttributes, Is.Null, label.Get ());
Assert.That (binding.Extensions, Is.Not.Null, label.Get ());
Assert.That (binding.Extensions.Count, Is.EqualTo (1), label.Get ());
- Assert.That (binding.Extensions [0], Is.InstanceOfType (typeof (WS.SoapBodyBinding)), label.Get ());
+ Assert.That (binding.Extensions [0], Is.AssignableTo<WS.SoapBodyBinding> (), label.Get ());
var body = (WS.SoapBodyBinding)binding.Extensions [0];
TestSoapBody (body, soap12, label);
label.LeaveScope ();
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
namespace MonoTests.System.ServiceModel.MetadataTests {
using System.ServiceModel.Description;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
using WS = System.Web.Services.Description;
using System.ServiceModel.Description;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
namespace MonoTests.System.ServiceModel.MetadataTests {
using System.ServiceModel.Description;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
using WS = System.Web.Services.Description;
using System.Text;
using NUnit.Framework;
using NUnit.Framework.Constraints;
-using NUnit.Framework.SyntaxHelpers;
using TextElement = System.ServiceModel.Channels.TextMessageEncodingBindingElement;
using BinaryElement = System.ServiceModel.Channels.BinaryMessageEncodingBindingElement;
<s:Fault>
<faultcode>a:ActionNotSupported</faultcode>
<faultstring xml:lang='en-US'>some error</faultstring>
+ <faultactor>Random</faultactor>
</s:Fault>
</s:Body>
</s:Envelope>";
+../../test-helpers/NunitHelpers.cs
System.ServiceProcess/ServiceBaseTest.cs
System.ServiceProcess/ServiceControllerTest.cs
System.ServiceProcess/ServiceControllerPermissionAttributeTest.cs
+../../test-helpers/NunitHelpers.cs
TestScheduler.cs
AssertEx.cs
Blocks.cs
Assert.IsTrue (transform.Post (1));
Assert.IsTrue (transform.Post (2));
- Assert.GreaterOrEqual (scheduler.ExecuteAll (), 1);
+ AssertHelper.GreaterOrEqual (scheduler.ExecuteAll (), 1);
Assert.AreEqual (2, Volatile.Read (ref n));
}
Assert.IsTrue (transform.Post (1));
Assert.IsTrue (transform.Post (2));
- Assert.GreaterOrEqual (scheduler.ExecuteAll (), 1);
+ AssertHelper.GreaterOrEqual (scheduler.ExecuteAll (), 1);
Assert.AreEqual (2, Volatile.Read (ref n));
}
Assert.IsFalse (transform.Post (101));
- Assert.GreaterOrEqual (scheduler.ExecuteAll (), 1);
+ AssertHelper.GreaterOrEqual (scheduler.ExecuteAll (), 1);
Assert.IsFalse (transform.Post (102));
Assert.IsNotNull (ex);
Assert.IsNotNull (ex.InnerException);
- Assert.IsInstanceOfType (typeof(OperationCanceledException),
+ Assert.IsInstanceOfType (typeof(TaskCanceledException),
ex.InnerException);
Assert.IsTrue (task.IsCompleted);
Assert.AreEqual (TaskStatus.Canceled, task.Status);
var queue = new ConcurrentQueue<Tuple<int, int>> ();
var block = factory (queue);
- Assert.IsEmpty (queue);
+ CollectionAssert.IsEmpty (queue);
for (int i = 0; i < 100; i++)
block.Post (i);
options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
- Assert.LessOrEqual (CalculateDegreeOfParallelism (taskIds), 2);
+ AssertHelper.LessOrEqual (CalculateDegreeOfParallelism (taskIds), 2);
options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
- Assert.LessOrEqual (CalculateDegreeOfParallelism (taskIds), 4);
+ AssertHelper.LessOrEqual (CalculateDegreeOfParallelism (taskIds), 4);
options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = -1 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
- Assert.LessOrEqual (CalculateDegreeOfParallelism (taskIds), taskIds.Length);
+ AssertHelper.LessOrEqual (CalculateDegreeOfParallelism (taskIds), taskIds.Length);
}
}
{
var options = new ExecutionDataflowBlockOptions ();
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
- Assert.GreaterOrEqual (taskIds.Distinct ().Count (), 1);
+ AssertHelper.GreaterOrEqual (taskIds.Distinct ().Count (), 1);
options = new ExecutionDataflowBlockOptions { MaxMessagesPerTask = 1 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
options = new ExecutionDataflowBlockOptions { MaxMessagesPerTask = 2 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
- Assert.GreaterOrEqual (taskIds.Distinct ().Count (), taskIds.Length / 2);
+ AssertHelper.GreaterOrEqual (taskIds.Distinct ().Count (), taskIds.Length / 2);
options = new ExecutionDataflowBlockOptions { MaxMessagesPerTask = 4 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
- Assert.GreaterOrEqual (taskIds.Distinct ().Count (), taskIds.Length / 4);
+ AssertHelper.GreaterOrEqual (taskIds.Distinct ().Count (), taskIds.Length / 4);
}
[Test]
+../../test-helpers/NunitHelpers.cs
../../System.Web/Test/mainsoft/MainsoftWebTest/HtmlAgilityPack/crc32.cs
../../System.Web/Test/mainsoft/MainsoftWebTest/HtmlAgilityPack/Header.cs
../../System.Web/Test/mainsoft/MainsoftWebTest/HtmlAgilityPack/HtmlAttribute.cs
Common/ITestDataContext.cs
Common/KnownResponseHeader.cs
Common/MiscExtensions.cs
-Common/Mocks.cs
Common/MyDynamicDataRouteHandler.cs
Common/MyHttpContextWrapper.cs
Common/MyHttpRequestWrapper.cs
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Web;
-
-using NUnit.Framework;
-using NUnit.Mocks;
-
-namespace MonoTests.Common
-{
- static class Mocks
- {
-
- }
-}
using System.IO;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
using System.Web.Routing;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
using System.Web.Routing;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
using System.IO;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
using System.IO;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
// Custom with UIHint attribute
mc = t.GetColumn ("CustomColumn2");
Assert.IsNotNull (mc.UIHint, "#A2");
- Assert.Greater (mc.UIHint.Length, 0, "#A2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#A2-1");
// Proves that UIHint on the column is not used, just the uiHint argument
AssertExtensions.Throws<InvalidOperationException> (() => {
// Custom with UIHint attribute
mc = t.GetColumn ("CustomColumn4");
Assert.IsNotNull (mc.UIHint, "#A4");
- Assert.Greater (mc.UIHint.Length, 0, "#A4-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#A4-1");
// Proves that UIHint on the column is not used, just the uiHint argument
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#A4-2");
mc = t.GetColumn ("DateTimeColumn2");
Assert.IsNotNull (mc.UIHint, "#B2");
- Assert.Greater (mc.UIHint.Length, 0, "#B2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#B2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "DateTime.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#B2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "DateTime.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#B2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "DateTime.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#B2-5");
mc = t.GetColumn ("DateColumn2");
Assert.IsNotNull (mc.UIHint, "#C2");
- Assert.Greater (mc.UIHint.Length, 0, "#C2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#C2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#C2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#C2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#C2-5");
mc = t.GetColumn ("DateColumn4");
Assert.IsNotNull (mc.UIHint, "#C4");
- Assert.Greater (mc.UIHint.Length, 0, "#C4-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#C4-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#C4-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#C4-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#C4-5");
mc = t.GetColumn ("TimeColumn2");
Assert.IsNotNull (mc.UIHint, "#D2");
- Assert.Greater (mc.UIHint.Length, 0, "#D2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#D2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#D2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#D2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#D2-5");
mc = t.GetColumn ("DurationColumn2");
Assert.IsNotNull (mc.UIHint, "#E2");
- Assert.Greater (mc.UIHint.Length, 0, "#E2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#E2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#E2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#E2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#E2-5");
mc = t.GetColumn ("PhoneNumberColumn2");
Assert.IsNotNull (mc.UIHint, "#F2");
- Assert.Greater (mc.UIHint.Length, 0, "#F2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#F2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#F2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#F2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#F2-5");
mc = t.GetColumn ("CurrencyColumn2");
Assert.IsNotNull (mc.UIHint, "#G2");
- Assert.Greater (mc.UIHint.Length, 0, "#G2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#G2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#G2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#G2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#G2-5");
mc = t.GetColumn ("TextColumn2");
Assert.IsNotNull (mc.UIHint, "#H2");
- Assert.Greater (mc.UIHint.Length, 0, "#H2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#H2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#H2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#H2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#H2-5");
mc = t.GetColumn ("HtmlColumn2");
Assert.IsNotNull (mc.UIHint, "#I2");
- Assert.Greater (mc.UIHint.Length, 0, "#I2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#I2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#I2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#I2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#I2-5");
mc = t.GetColumn ("MultilineTextColumn2");
Assert.IsNotNull (mc.UIHint, "#J2");
- Assert.Greater (mc.UIHint.Length, 0, "#J2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#J2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#J2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#J2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#J2-5");
mc = t.GetColumn ("EmailAddressColumn2");
Assert.IsNotNull (mc.UIHint, "#K2");
- Assert.Greater (mc.UIHint.Length, 0, "#K2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#K2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#K2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#K2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#K2-5");
mc = t.GetColumn ("PasswordColumn2");
Assert.IsNotNull (mc.UIHint, "#L2");
- Assert.Greater (mc.UIHint.Length, 0, "#L2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#L2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#L2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#L2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#L2-5");
mc = t.GetColumn ("UrlColumn2");
Assert.IsNotNull (mc.UIHint, "#M2");
- Assert.Greater (mc.UIHint.Length, 0, "#M2-1");
+ AssertHelper.Greater (mc.UIHint.Length, 0, "#M2-1");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, null), "#M2-3");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, String.Empty), "#M2-4");
Assert.AreEqual (ftf.TemplateFolderVirtualPath + "Text.ascx", ftf.GetFieldTemplateVirtualPath (mc, DataBoundControlMode.ReadOnly, "Boolean.ascx"), "#M2-5");
using System.IO;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
using System.Web.Routing;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
using System.Web.Routing;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
using System.Web.UI.WebControls;
using NUnit.Framework;
-using NUnit.Mocks;
using MonoTests.stand_alone.WebHarness;
using MonoTests.SystemWeb.Framework;
using MonoTests.Common;
+../../test-helpers/NunitHelpers.cs
Test/standalone-tests/Consts.cs
Test/standalone-tests/Locations.cs
Test/standalone-tests/OutputCacheProvider.cs
+../../test-helpers/NunitHelpers.cs
../../System.Web.DynamicData/Test/Common/AssertExtensions.cs
mainsoft/MainsoftWebTest/HtmlAgilityPack/AssemblyInfo.cs
mainsoft/MainsoftWebTest/HtmlAgilityPack/crc32.cs
Assert.IsNull (HostingEnvironment.InitializationException, "During:InitializationException");
Assert.IsTrue (HostingEnvironment.IsHosted, "During:IsHosted");
Assert.IsNotNull (HostingEnvironment.ApplicationID, "During:ApplicationID:Null");
- Assert.IsNotEmpty (HostingEnvironment.ApplicationID, "During:ApplicationID:Empty");
+ AssertHelper.IsNotEmpty (HostingEnvironment.ApplicationID, "During:ApplicationID:Empty");
Assert.IsNotNull (HostingEnvironment.ApplicationPhysicalPath, "During:ApplicationPhysicalPath:Null");
- Assert.IsNotEmpty (HostingEnvironment.ApplicationPhysicalPath, "During:ApplicationPhysicalPath:Empty");
+ AssertHelper.IsNotEmpty (HostingEnvironment.ApplicationPhysicalPath, "During:ApplicationPhysicalPath:Empty");
Assert.IsNotNull (HostingEnvironment.ApplicationVirtualPath, "During:ApplicationVirtualPath:Null");
- Assert.IsNotEmpty (HostingEnvironment.ApplicationVirtualPath, "During:ApplicationVirtualPath:Empty");
+ AssertHelper.IsNotEmpty (HostingEnvironment.ApplicationVirtualPath, "During:ApplicationVirtualPath:Empty");
Assert.IsNotNull (HostingEnvironment.SiteName, "During:SiteName:Null");
- Assert.IsNotEmpty (HostingEnvironment.SiteName, "During:SiteName:Empty");
+ AssertHelper.IsNotEmpty (HostingEnvironment.SiteName, "During:SiteName:Empty");
Assert.IsNotNull (HostingEnvironment.Cache, "During:Cache");
Assert.AreEqual (ApplicationShutdownReason.None, HostingEnvironment.ShutdownReason, "During:ShutdownReason");
Assert.IsNotNull (HostingEnvironment.VirtualPathProvider, "During:VirtualPathProvider");
KnownResponseHeader known;
- Assert.LessOrEqual (1, f.KnownResponseHeaders.Count, "#B1");
+ AssertHelper.LessOrEqual (1, f.KnownResponseHeaders.Count, "#B1");
known = (KnownResponseHeader)f.KnownResponseHeaders ["Content-Type"];
Assert.AreEqual (HttpWorkerRequest.HeaderContentType, known.Index, "#B2");
KnownResponseHeader known;
- Assert.LessOrEqual (1, f.KnownResponseHeaders.Count, "#B1");
+ AssertHelper.LessOrEqual (1, f.KnownResponseHeaders.Count, "#B1");
known = (KnownResponseHeader)f.KnownResponseHeaders ["Content-Type"];
Assert.AreEqual (HttpWorkerRequest.HeaderContentType, known.Index, "#B2");
[Test]
[Category ("NunitWeb")]
[Ignore ("Pending fix for bug 351878")]
- [Explicit]
public void UnloadAppDomain100Times ()
{
for (int i = 0; i < 100; i++)
provider.DoAddNode (node, rootNode);
Assert.IsNotNull (provider.CallTrace, "#A1");
- Assert.Greater (provider.CallTrace.Length, 1, "#A1-1");
+ AssertHelper.Greater (provider.CallTrace.Length, 1, "#A1-1");
Assert.AreEqual (provider.CallTrace[0].Name, "BuildSiteMap", "#A1-2");
}
Assert.IsNotNull (provider.RootNode, "#A1");
Assert.AreEqual (provider.RootNode.Provider, provider, "#A2");
Assert.IsNotNull (provider.CallTrace, "#A3");
- Assert.Greater (provider.CallTrace.Length, 1, "#A3-1");
+ AssertHelper.Greater (provider.CallTrace.Length, 1, "#A3-1");
Assert.AreEqual ("BuildSiteMap", provider.CallTrace[0].Name, "#A3-2");
Assert.AreEqual ("get_RootNode", provider.CallTrace[1].Name, "#A3-3");
}
+../../test-helpers/NunitHelpers.cs
../../../build/common/Consts.cs
System.Windows.Forms/ApplicationTest.cs
System.Windows.Forms/AutoCompleteStringCollectionTest.cs
Assert.IsNotNull (returnedNode, "#A1");
object val = returnedNode.GetValue (new ReturnSerializableSubClassITRS ());
- Assert.IsNotInstanceOfType (typeof (serializableSubClass), val, "#A2");
+ AssertHelper.IsNotInstanceOfType (typeof (serializableSubClass), val, "#A2");
Assert.IsInstanceOfType (typeof (serializable), val, "#A3");
}
node = GetNodeFileRefToSerializable ("ser.bbb",true);
object val = node.GetValue (new ReturnSerializableSubClassITRS ());
- Assert.IsNotInstanceOfType (typeof (serializableSubClass), val, "#A1");
+ AssertHelper.IsNotInstanceOfType (typeof (serializableSubClass), val, "#A1");
Assert.IsInstanceOfType (typeof (serializable), val, "#A2");
}
// get value passing no params
object val = returnedNode.GetValue ((ITypeResolutionService) null);
Assert.IsInstanceOfType (typeof (serializable), val, "#A2");
- Assert.IsNotInstanceOfType (typeof (serializableSubClass), val, "#A3");
+ AssertHelper.IsNotInstanceOfType (typeof (serializableSubClass), val, "#A3");
//get value type passing different params
string newType = returnedNode.GetValueTypeName (new ReturnSerializableSubClassITRS ());
object defaultVal = returnedNode.GetValue ((ITypeResolutionService) null);
Assert.IsInstanceOfType (typeof (serializable), defaultVal, "#A2");
- Assert.IsNotInstanceOfType (typeof (serializableSubClass), defaultVal, "#A3");
+ AssertHelper.IsNotInstanceOfType (typeof (serializableSubClass), defaultVal, "#A3");
object newVal = returnedNode.GetValue (new ReturnSerializableSubClassITRS ());
- Assert.IsNotInstanceOfType (typeof (serializableSubClass), newVal, "#A4");
+ AssertHelper.IsNotInstanceOfType (typeof (serializableSubClass), newVal, "#A4");
Assert.IsInstanceOfType (typeof (serializable), newVal, "#A5");
}
// get value passing null params
object val = returnedNode.GetValue ((ITypeResolutionService) null);
- // Assert.IsNotInstanceOfType (typeof (serializable), val, "#A5"); this would fail as subclasses are id-ed as instances of parents
+ // AssertHelper.IsNotInstanceOfType (typeof (serializable), val, "#A5"); this would fail as subclasses are id-ed as instances of parents
Assert.IsInstanceOfType (typeof (serializableSubClass), val, "#A4");
}
object o = node.GetValue ((AssemblyName []) null);
- Assert.IsNotInstanceOfType (typeof (serializableSubClass), o, "#A2");
+ AssertHelper.IsNotInstanceOfType (typeof (serializableSubClass), o, "#A2");
Assert.IsInstanceOfType (typeof (serializable), o, "#A3");
rr.Close ();
}
Assert.IsNotNull (finalNode, "#A3");
object finalVal = finalNode.GetValue ((ITypeResolutionService) null);
- Assert.IsNotInstanceOfType (typeof (serializableSubClass), finalVal, "#A4");
+ AssertHelper.IsNotInstanceOfType (typeof (serializableSubClass), finalVal, "#A4");
Assert.IsInstanceOfType (typeof (serializable), finalVal, "#A5");
}
}
[Test]
+ [Ignore ("causes an infinite restart loop since we're not in a separate AppDomain with nunit-lite")]
[ExpectedException (typeof (NotSupportedException))]
public void RestartNotSupportedExceptionTest ()
{
Assert.AreEqual (31, p.GetRowHeights ()[0], "D1");\r
Assert.AreEqual (31, p.GetRowHeights ()[1], "D2");\r
Assert.AreEqual (81, p.GetColumnWidths ()[0], "D3");\r
- Assert.LessOrEqual (75, p.GetColumnWidths ()[1], "D4");\r
- Assert.GreaterOrEqual (78, p.GetColumnWidths ()[1], "D5");\r
- Assert.LessOrEqual (78, p.GetColumnWidths ()[2], "D6");\r
- Assert.GreaterOrEqual (81, p.GetColumnWidths ()[2], "D7");\r
+ AssertHelper.LessOrEqual (75, p.GetColumnWidths ()[1], "D4");\r
+ AssertHelper.GreaterOrEqual (78, p.GetColumnWidths ()[1], "D5");\r
+ AssertHelper.LessOrEqual (78, p.GetColumnWidths ()[2], "D6");\r
+ AssertHelper.GreaterOrEqual (81, p.GetColumnWidths ()[2], "D7");\r
}\r
\r
[Test]\r
Assert.AreEqual (4, tlp.RowCount, "X18638-1");\r
Assert.AreEqual (3, tlp.ColumnCount, "X18638-2");\r
Assert.AreEqual (60, widths[0], "X18638-3");\r
- Assert.Greater (label2.Width, widths[1], "X18638-5");\r
+ AssertHelper.Greater (label2.Width, widths[1], "X18638-5");\r
Assert.AreEqual (45, widths[2], "X18638-4");\r
}\r
\r
Assert.AreEqual (string.Format(CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
" this.namesField = value;{0}" +
" }}{0}" +
" }}{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
codeNamespace = ExportCode (typeof (ArrayClass[]));
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
" this.namesField = value;{0}" +
" }}{0}" +
" }}{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#4");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#4");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
" this.itemsField = value;{0}" +
" }}{0}" +
" }}{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
" this.cdataField = value;{0}" +
" }}{0}" +
" }}{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
" this.myChoiceField = value;{0}" +
" }}{0}" +
" }}{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
"{0}" +
"/// <remarks/>{0}" +
"[System.FlagsAttribute()]{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"public enum MapModifiers {{{0}" +
" {0}" +
" /// <remarks/>{0}" +
" [System.Xml.Serialization.XmlEnumAttribute(\"protected\")]{0}" +
" Protected = 2,{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Xml.Serialization.XmlTypeAttribute(IncludeInSchema=false)]{0}" +
"[System.Xml.Serialization.XmlRootAttribute(Namespace=\"\", IsNullable=false)]{0}" +
" {0}" +
" /// <remarks/>{0}" +
" ChoiceTwo,{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
codeNamespace = ExportCode (typeof (ItemChoiceType[]));
Assert.IsNotNull (codeNamespace, "#3");
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Xml.Serialization.XmlTypeAttribute(IncludeInSchema=false)]{0}" +
"public enum ItemChoiceType {{{0}" +
" {0}" +
" /// <remarks/>{0}" +
" ChoiceTwo,{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#4");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#4");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
"}}{0}" +
"{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
" this.somethingField = value;{0}" +
" }}{0}" +
" }}{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
"}}{0}" +
"{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
"{0}" +
"/// <remarks/>{0}" +
"[System.FlagsAttribute()]{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Xml.Serialization.XmlTypeAttribute(Namespace=\"some:urn\")]{0}" +
"public enum FlagEnum {{{0}" +
"{0}" +
"/// <remarks/>{0}" +
"[System.FlagsAttribute()]{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Xml.Serialization.XmlTypeAttribute(Namespace=\"urn:myNS\")]{0}" +
"public enum FlagEnum {{{0}" +
"{0}" +
"/// <remarks/>{0}" +
"[System.FlagsAttribute()]{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Xml.Serialization.XmlTypeAttribute(Namespace=\"urn:myNS\")]{0}" +
"public enum FlagEnum_Encoded {{{0}" +
" {0}" +
" /// <remarks/>{0}" +
" e4 = 4,{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
"{0}{0}" +
"/// <remarks/>{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Diagnostics.DebuggerStepThroughAttribute()]{0}" +
"[System.ComponentModel.DesignerCategoryAttribute(\"code\")]{0}" +
" this.somethingField = value;{0}" +
" }}{0}" +
" }}{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
"{0}{0}" +
"/// <remarks/>{0}" +
"[System.FlagsAttribute()]{0}" +
- "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Xml\", \"{1}\")]{0}" +
+ "[System.CodeDom.Compiler.GeneratedCodeAttribute(\"nunit-lite-console\", \"0.0.0.0\")]{0}" +
"[System.SerializableAttribute()]{0}" +
"[System.Xml.Serialization.XmlRootAttribute(Namespace=\"\", IsNullable=false)]{0}" +
"public enum ZeroFlagEnum {{{0}" +
" /// <remarks/>{0}" +
" [System.Xml.Serialization.XmlEnumAttribute(\"tns:t<w>o\")]{0}" +
" e2 = 4,{0}" +
- "}}{0}", Environment.NewLine, XmlFileVersion), sw.ToString (), "#2");
+ "}}{0}", Environment.NewLine), sw.ToString (), "#2");
}
[Test]
return codeNamespace;
}
- string XmlFileVersion {
- get {
- Assembly xmlAsm = typeof (XmlDocument).Assembly;
- AssemblyFileVersionAttribute afv = (AssemblyFileVersionAttribute)
- Attribute.GetCustomAttribute (xmlAsm, typeof (AssemblyFileVersionAttribute));
- return afv.Version;
- }
- }
-
[XmlRootAttribute ("root", Namespace="urn:aNS", IsNullable=false)]
public class Root
{
Assert.AreEqual ("file", resolved.Scheme);
var task = sr.GetEntityAsync (resolved, null, typeof (Stream));
Assert.That (task.Wait (3000));
- Assert.IsInstanceOfType (typeof (Stream), task.Result);
+ Assert.IsInstanceOfType (typeof (FileStream), task.Result);
}
}
+../../test-helpers/NunitHelpers.cs
System.Xml.Linq/ExtensionsTest.cs
System.Xml.Linq/XAttributeTest.cs
System.Xml.Linq/XCommentTest.cs
}
}
- Assert.GreaterOrEqual (afterNoOfAttributes, beforeNoOfAttributes, "newAttributes");
- Assert.GreaterOrEqual (afterNoOfElements, beforeNoOfElements, "newElements");
+ AssertHelper.GreaterOrEqual (afterNoOfAttributes, beforeNoOfAttributes, "newAttributes");
+ AssertHelper.GreaterOrEqual (afterNoOfElements, beforeNoOfElements, "newElements");
}
/*
TEST_MCS_FLAGS = -nowarn:618,672,219,67,169,612 \
$(foreach f, $(TEST_RESOURCES), -resource:$(f),$(notdir $(f)))
+TEST_NUNITLITE_APP_CONFIG_GLOBAL=Test/test-config-file
+
REFERENCE_SOURCES_FLAGS = -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX
ifndef NO_PROCESS_START
REFERENCE_SOURCES_FLAGS += -d:MONO_FEATURE_PROCESS_START
EXTRA_DISTFILES = \
Test/test-config-file \
- Test/test-config-file-net-2.0 \
Test/System.Security.Cryptography.X509Certificates/pkits/Makefile \
Test/System.Security.Cryptography.X509Certificates/pkits/README \
Test/System.Security.Cryptography.X509Certificates/pkits/x509build.cs \
$(build_lib): $(CYCLIC_DEP_FILES)
-$(test_lib): $(test_lib).config $(TEST_RESOURCES)
-
-$(test_lib).config: Test/test-config-file
- cp $< $@
+$(test_lib): $(TEST_RESOURCES)
CLEAN_FILES = $(test_lib).config $(bare_libdir)/System.dll $(secxml_libdir)/System.dll $(bare_libdir)/System.dll.mdb $(secxml_libdir)/System.dll.mdb
[DllImport (BTLS_DYLIB)]
extern static int mono_btls_x509_lookup_add_mono (IntPtr handle, IntPtr monoLookup);
- [DllImport (BTLS_DYLIB)]
- extern static void mono_btls_x509_lookup_method_mono_init (
- IntPtr handle, IntPtr instance, IntPtr by_subject_func);
-
[DllImport (BTLS_DYLIB)]
extern static int mono_btls_x509_lookup_init (IntPtr handle);
+++ /dev/null
-//
-// MonoBtlsX509NameList.cs
-//
-// Author:
-// Martin Baulig <martin.baulig@xamarin.com>
-//
-// 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.
-#if SECURITY_DEP && MONO_FEATURE_BTLS
-using System;
-using System.IO;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
-
-namespace Mono.Btls
-{
- class MonoBtlsX509NameList : MonoBtlsObject
- {
- internal class BoringX509NameListHandle : MonoBtlsHandle
- {
- bool dontFree;
-
- internal BoringX509NameListHandle (IntPtr handle, bool ownsHandle)
- : base (handle, ownsHandle)
- {
- this.dontFree = !ownsHandle;
- }
-
- protected override bool ReleaseHandle ()
- {
- if (!dontFree)
- mono_btls_x509_name_list_free (handle);
- return true;
- }
- }
-
- [DllImport (BTLS_DYLIB)]
- extern static IntPtr mono_btls_x509_name_list_new ();
-
- [DllImport (BTLS_DYLIB)]
- extern static int mono_btls_x509_name_list_get_count (IntPtr handle);
-
- [DllImport (BTLS_DYLIB)]
- extern static int mono_btls_x509_name_list_add (IntPtr handle, IntPtr name);
-
- [DllImport (BTLS_DYLIB)]
- extern static IntPtr mono_btls_x509_name_list_get_item (IntPtr handle, int index);
-
- [DllImport (BTLS_DYLIB)]
- extern static void mono_btls_x509_name_list_free (IntPtr handle);
-
- new internal BoringX509NameListHandle Handle {
- get { return (BoringX509NameListHandle)base.Handle; }
- }
-
- internal MonoBtlsX509NameList (BoringX509NameListHandle handle)
- : base (handle)
- {
- }
-
- internal MonoBtlsX509NameList ()
- : this (Create_internal ())
- {
- }
-
- static BoringX509NameListHandle Create_internal ()
- {
- var handle = mono_btls_x509_name_list_new ();
- if (handle == IntPtr.Zero)
- throw new MonoBtlsException ();
- return new BoringX509NameListHandle (handle, true);
- }
-
- public int GetCount ()
- {
- CheckThrow ();
- return mono_btls_x509_name_list_get_count (
- Handle.DangerousGetHandle ());
- }
-
- public MonoBtlsX509Name GetItem (int index)
- {
- CheckThrow ();
- if (index < 0 || index >= GetCount ())
- throw new ArgumentOutOfRangeException ();
- var ptr = mono_btls_x509_name_list_get_item (
- Handle.DangerousGetHandle (), index);
- if (ptr == IntPtr.Zero)
- return null;
- return new MonoBtlsX509Name (
- new MonoBtlsX509Name.BoringX509NameHandle (ptr, true));
- }
-
- public void Add (MonoBtlsX509Name name)
- {
- CheckThrow ();
- mono_btls_x509_name_list_add (
- Handle.DangerousGetHandle (),
- name.Handle.DangerousGetHandle ());
- }
- }
-}
-#endif
#if SECURITY_DEP
using System;
using MSI = Mono.Security.Interface;
+#if MONO_FEATURE_BTLS
using Mono.Btls;
+#endif
namespace Mono.Net.Security
{
case "default":
case "legacy":
return new LegacyTlsProvider ();
+#if MONO_FEATURE_BTLS
case "btls":
if (!IsBtlsSupported ())
throw new NotSupportedException ("BTLS in not supported!");
return new MonoBtlsProvider ();
+#endif
default:
throw new NotSupportedException (string.Format ("Invalid TLS Provider: `{0}'.", provider));
}
namespace System.Net
{
- static class UnsafeNclNativeMethods
+ static partial class UnsafeNclNativeMethods
{
internal static unsafe class HttpApi
{
--- /dev/null
+using System.Security;
+using System.Runtime.InteropServices;
+
+namespace System.Net
+{
+ static partial class UnsafeNclNativeMethods
+ {
+ internal unsafe static class SecureStringHelper
+ {
+ internal static string CreateString(SecureString secureString)
+ {
+ string plainString;
+ IntPtr bstr = IntPtr.Zero;
+
+ if (secureString == null || secureString.Length == 0)
+ return String.Empty;
+
+ try
+ {
+ bstr = Marshal.SecureStringToBSTR(secureString);
+ plainString = Marshal.PtrToStringBSTR(bstr);
+ }
+ finally
+ {
+ if (bstr != IntPtr.Zero)
+ Marshal.ZeroFreeBSTR(bstr);
+ }
+ return plainString;
+ }
+
+ internal static SecureString CreateSecureString(string plainString)
+ {
+ SecureString secureString;
+
+ if (plainString == null || plainString.Length == 0)
+ return new SecureString();
+
+ fixed (char* pch = plainString)
+ {
+ secureString = new SecureString(pch, plainString.Length);
+ }
+
+ return secureString;
+ }
+ }
+ }
+}
\ No newline at end of file
<Compile Include="..\referencesource\System\net\System\Net\mail\TransferEncoding.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\mail\WriteStateInfoBase.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkAccess.cs" />\r
+ <Compile Include="..\referencesource\System\net\System\Net\NetworkCredential.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\DuplicateAddressDetectionState.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\GatewayIPAddressInformation.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\GatewayIPAddressInformationCollection.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509LookupType.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Name.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509NameEntryType.cs" />\r
- <Compile Include="Mono.Btls\MonoBtlsX509NameList.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Purpose.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Revoked.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Store.cs" />\r
<Compile Include="ReferenceSources\Logging.cs" />\r
<Compile Include="ReferenceSources\NativeMethods.cs" />\r
<Compile Include="ReferenceSources\RequestCacheProtocol.cs" />\r
+ <Compile Include="ReferenceSources\SecureStringHelper.cs" />\r
<Compile Include="ReferenceSources\SettingsSectionInternal.cs" />\r
<Compile Include="ReferenceSources\Socket.cs" />\r
<Compile Include="ReferenceSources\SR.cs" />\r
<Compile Include="System.Net\MacProxy.cs" />\r
<Compile Include="System.Net\MonoHttpDate.cs" />\r
<Compile Include="System.Net\NetConfig.cs" />\r
- <Compile Include="System.Net\NetworkCredential.cs" />\r
<Compile Include="System.Net\NtlmClient.cs" />\r
<Compile Include="System.Net\RequestStream.cs" />\r
<Compile Include="System.Net\ResponseStream.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\mail\TransferEncoding.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\mail\WriteStateInfoBase.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkAccess.cs" />\r
+ <Compile Include="..\referencesource\System\net\System\Net\NetworkCredential.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\DuplicateAddressDetectionState.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\GatewayIPAddressInformation.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\GatewayIPAddressInformationCollection.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509LookupType.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Name.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509NameEntryType.cs" />\r
- <Compile Include="Mono.Btls\MonoBtlsX509NameList.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Purpose.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Revoked.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Store.cs" />\r
<Compile Include="ReferenceSources\Logging.cs" />\r
<Compile Include="ReferenceSources\NativeMethods.cs" />\r
<Compile Include="ReferenceSources\RequestCacheProtocol.cs" />\r
+ <Compile Include="ReferenceSources\SecureStringHelper.cs" />\r
<Compile Include="ReferenceSources\SettingsSectionInternal.cs" />\r
<Compile Include="ReferenceSources\Socket.cs" />\r
<Compile Include="ReferenceSources\SR.cs" />\r
<Compile Include="System.Net\MacProxy.cs" />\r
<Compile Include="System.Net\MonoHttpDate.cs" />\r
<Compile Include="System.Net\NetConfig.cs" />\r
- <Compile Include="System.Net\NetworkCredential.cs" />\r
<Compile Include="System.Net\NtlmClient.cs" />\r
<Compile Include="System.Net\RequestStream.cs" />\r
<Compile Include="System.Net\ResponseStream.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\mail\TransferEncoding.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\mail\WriteStateInfoBase.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkAccess.cs" />\r
+ <Compile Include="..\referencesource\System\net\System\Net\NetworkCredential.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\DuplicateAddressDetectionState.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\GatewayIPAddressInformation.cs" />\r
<Compile Include="..\referencesource\System\net\System\Net\NetworkInformation\GatewayIPAddressInformationCollection.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509LookupType.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Name.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509NameEntryType.cs" />\r
- <Compile Include="Mono.Btls\MonoBtlsX509NameList.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Purpose.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Revoked.cs" />\r
<Compile Include="Mono.Btls\MonoBtlsX509Store.cs" />\r
<Compile Include="ReferenceSources\Logging.cs" />\r
<Compile Include="ReferenceSources\NativeMethods.cs" />\r
<Compile Include="ReferenceSources\RequestCacheProtocol.cs" />\r
+ <Compile Include="ReferenceSources\SecureStringHelper.cs" />\r
<Compile Include="ReferenceSources\SettingsSectionInternal.cs" />\r
<Compile Include="ReferenceSources\Socket.cs" />\r
<Compile Include="ReferenceSources\SR.cs" />\r
<Compile Include="System.Net\MacProxy.cs" />\r
<Compile Include="System.Net\MonoHttpDate.cs" />\r
<Compile Include="System.Net\NetConfig.cs" />\r
- <Compile Include="System.Net\NetworkCredential.cs" />\r
<Compile Include="System.Net\NtlmClient.cs" />\r
<Compile Include="System.Net\RequestStream.cs" />\r
<Compile Include="System.Net\ResponseStream.cs" />\r
{
ThrowIfDisposedAndClosed ();
- if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.ReuseAddress && optionValue != 0 && !SupportsPortReuse (protocolType))
- throw new SocketException ((int) SocketError.OperationNotSupported, "Operating system sockets do not support ReuseAddress.\nIf your socket is not intended to bind to the same address and port multiple times remove this option, otherwise you should ignore this exception inside a try catch and check that ReuseAddress is true before binding to the same address and port multiple times.");
-
int error;
SetSocketOption_internal (m_Handle, optionLevel, optionName, null, null, optionValue, out error);
+++ /dev/null
-//
-// System.Net.NetworkCredential.cs
-//
-// Authors: Duncan Mak (duncan@ximian.com)
-// Rolf Bjarne KVinge (rolf@xamarin.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// (C) Ximian, Inc.
-// Copyright (C) 2010 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2011, 2014 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.Security;
-
-namespace System.Net
-{
- public class NetworkCredential : ICredentials
- , ICredentialsByHost
- {
- // Fields
- string userName;
- string password;
- string domain;
-
- SecureString securePassword;
-
- // Constructors
- public NetworkCredential ()
- {
- }
-
- public NetworkCredential (string userName, string password)
- {
- this.userName = userName;
- this.password = password;
- }
-
- public NetworkCredential (string userName, string password, string domain)
- : this (userName, password)
- {
- this.domain = domain;
- }
-
- public NetworkCredential (string userName, SecureString password)
- {
- this.userName = userName;
- SecurePassword = password;
- }
-
- public NetworkCredential (string userName, SecureString password, string domain)
- : this (userName, password)
- {
- this.domain = domain;
- }
- // Properties
-
- public string Domain {
- get { return domain ?? String.Empty; }
- set { domain = value; }
- }
-
- public string UserName {
- get { return userName ?? String.Empty; }
- set { userName = value; }
- }
-
- public string Password {
- get { return password ?? String.Empty; }
- set { password = value; }
- }
-
- public SecureString SecurePassword {
- get { return securePassword; }
- set {
- if (value == null) {
- securePassword = new SecureString ();
- } else {
- securePassword = value;
- }
- }
- }
-
- public NetworkCredential GetCredential (Uri uri, string authType)
- {
- return this;
- }
-
- public NetworkCredential GetCredential (string host, int port, string authenticationType)
- {
- return this;
- }
- }
-}
System.Net/MacProxy.cs
System.Net/MonoHttpDate.cs
System.Net/NetConfig.cs
-System.Net/NetworkCredential.cs
System.Net.NetworkInformation/IcmpV4Statistics.cs
System.Net.NetworkInformation/IcmpV6Statistics.cs
System.Net.NetworkInformation/IPAddressCollection.cs
Mono.Btls/MonoBtlsX509LookupMono.cs
Mono.Btls/MonoBtlsX509LookupType.cs
Mono.Btls/MonoBtlsX509Name.cs
-Mono.Btls/MonoBtlsX509NameList.cs
Mono.Btls/MonoBtlsX509NameEntryType.cs
Mono.Btls/MonoBtlsX509Purpose.cs
Mono.Btls/MonoBtlsX509Revoked.cs
ReferenceSources/NativeMethods.cs
ReferenceSources/RequestCacheProtocol.cs
ReferenceSources/SettingsSectionInternal.cs
+ReferenceSources/SecureStringHelper.cs
ReferenceSources/Socket.cs
ReferenceSources/SR.cs
ReferenceSources/SR2.cs
../referencesource/System/net/System/Net/IWebProxyFinder.cs
../referencesource/System/net/System/Net/IWebRequestCreate.cs
../referencesource/System/net/System/Net/NetworkAccess.cs
+../referencesource/System/net/System/Net/NetworkCredential.cs
../referencesource/System/net/System/Net/ProtocolViolationException.cs
../referencesource/System/net/System/Net/TransportContext.cs
../referencesource/System/net/System/Net/TransportType.cs
using System.Security.Cryptography.X509Certificates;
#if SECURITY_DEP
using MSX = Mono.Security.X509;
+#if MONO_FEATURE_BTLS
using Mono.Btls;
#endif
+#endif
namespace System {
"TrustEvaluateSsl",
ignoreCase:false,
throwOnBindFailure:true);
+#if MONO_FEATURE_BTLS
certStoreLookup = (Func<long, bool, byte[]>)
Delegate.CreateDelegate (typeof (Func<long, bool, byte[]>),
t,
"CertStoreLookup",
ignoreCase:false,
throwOnBindFailure:true);
+#endif // MONO_FEATURE_BTLS
#endif // SECURITY_DEP
getDefaultProxy = (Func<IWebProxy>)Delegate.CreateDelegate (
typeof (Func<IWebProxy>), t, "GetDefaultProxy",
return trustEvaluateSsl (certsRawData);
}
+#if MONO_FEATURE_BTLS
internal static MonoBtlsX509 CertStoreLookup (MonoBtlsX509Name name)
{
var hash = name.GetHash ();
return MonoBtlsX509.LoadFromData (result, MonoBtlsX509Format.DER);
}
+#endif // MONO_FEATURE_BTLS
#endif // SECURITY_DEP
internal static IWebProxy GetDefaultProxy ()
+../../test-helpers/NunitHelpers.cs
Microsoft.CSharp/CodeGeneratorFromCompileUnitTest.cs
Microsoft.CSharp/CodeGeneratorFromExpressionTest.cs
Microsoft.CSharp/CodeGeneratorFromNamespaceTest.cs
int importPosition = result.IndexOf (IMPORT);
int attributePosition = result.IndexOf (ATTRIBUTE);
- Assert.Greater (attributePosition, importPosition, "Actual order: " + result);
+ AssertHelper.Greater (attributePosition, importPosition, "Actual order: " + result);
}
[Test]
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Collections.Generic
{
public void ConstructorNullName ()
{
SourceSwitch s = new SourceSwitch (null);
- Assert.IsEmpty (s.DisplayName);
+ AssertHelper.IsEmpty (s.DisplayName);
}
[Test]
public void NullSwitchHasEmptyDisplayNameAndDescription ()
{
var s = new TestNullSwitch ();
- Assert.IsEmpty (s.DisplayName);
- Assert.IsEmpty (s.Description);
+ AssertHelper.IsEmpty (s.DisplayName);
+ AssertHelper.IsEmpty (s.Description);
}
}
}
using (var unZippedStream = new StreamReader (gZipStream, Encoding.UTF8)) {
unZipped = unZippedStream.ReadToEnd ();
}
+
+ Assert.AreEqual(1877, unZipped.Length);
+ }
+
+ [Test]
+ public void Bug44994_Inflate()
+ {
+ var base64String = @"7cWxCQAgDACwpeBjgqsgXiHU0fd9QzBLErX1EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADepcxcuU/atm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm37zy8=";
+
+ byte[] byteArray = Convert.FromBase64String(base64String);
+ string unZipped = null;
+
+ using (var zippedMemoryStream = new MemoryStream(byteArray))
+ using (var gZipStream = new DeflateStream(zippedMemoryStream, CompressionMode.Decompress))
+ using (var unzippedMemStream = new MemoryStream())
+ using (var unZippedStream = new StreamReader(gZipStream, Encoding.UTF8))
+ {
+ unZipped = unZippedStream.ReadToEnd();
+ }
+
+ Assert.AreEqual(81942, unZipped.Length);
+ }
+
+ [Test]
+ [Category ("MobileNotWorking")]
+ public void Bug44994_InflateByteByByte()
+ {
+ int byteCount = 0;
+ using (var fileStream = File.OpenRead(Path.Combine("Test", "compressed.bin")))
+ {
+ using (var deflateStream = new DeflateStream(fileStream, CompressionMode.Decompress, false))
+ {
+ while (deflateStream.ReadByte() != -1)
+ {
+ byteCount++;
+ }
+ }
+ }
+
+ Assert.AreEqual(125387, byteCount);
}
}
}
using System;
using System.Net;
+using System.Security;
using NUnit.Framework;
nc = new NetworkCredential ("user", "********", "dom");
CheckCustom (nc);
}
+
+ [Test]
+ public void DecipherSecureString ()
+ {
+ // many code snippets suggest using the following to get the decrypted string from a SecureString
+ var ss = new SecureString ();
+ ss.AppendChar('h');
+ ss.AppendChar('e');
+ ss.AppendChar('l');
+ ss.AppendChar('l');
+ ss.AppendChar('o');
+
+ string plain = new NetworkCredential (string.Empty, ss).Password;
+ Assert.AreEqual ("hello", plain);
+ }
}
}
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
+using System.Reflection;
namespace MonoTests.System.Security.Cryptography.X509Certificates {
public void FixtureSetUp ()
{
base_dir = String.Format ("{0}{1}Test{1}System.Security.Cryptography.X509Certificates{1}pkits{1}certs",
- Directory.GetCurrentDirectory (), Path.DirectorySeparatorChar);
+ Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location), Path.DirectorySeparatorChar);
if (!Directory.Exists (base_dir))
Assert.Ignore ("PKITS tests data not found under '{0}'.", new object[] { base_dir });
[TestFixtureTearDown]
public void FixtureTearDown ()
{
- cache.Clear ();
+ if (cache != null)
+ cache.Clear ();
// clean-up, as best as possible, the stores
}
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
<system.diagnostics>
<switches>
<!-- Boolean switches: any non-zero value is true -->
<add name="trace-negative" value="-1"/>
</switches>
</system.diagnostics>
-</configuration>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <system.diagnostics>
- <sources>
- <source name="source1" switchName="switch" switchType="System.Diagnostics.SourceSwitch">
- <!--
- <listeners>
- <add name="console" type="System.Diagnostics.ConsoleTraceListener"/>
- </listeners>
- -->
- </source>
- </sources>
- <switches>
- <!-- Boolean switches: any non-zero value is true -->
- <add name="bool-true" value="1"/>
- <add name="bool-true-2" value="4"/>
- <add name="bool-true-3" value="-2"/>
- <add name="bool-false" value="0"/>
-
- <!-- trace switches: -->
- <add name="trace-off" value="0"/>
- <add name="trace-error" value="1"/>
- <add name="trace-warning" value="2"/>
- <add name="trace-info" value="3"/>
- <add name="trace-verbose" value="4"/>
-
- <!-- custom switches: -->
- <add name="custom-switch" value="42"/>
-
- <!-- this causes problems on .NET -->
- <add name="trace-negative" value="-1"/>
- </switches>
- </system.diagnostics>
-</configuration>
-
System.Net/MacProxy.cs
System.Net/MonoHttpDate.cs
System.Net/NetConfig.cs
-System.Net/NetworkCredential.cs
System.Net/NtlmClient.cs
System.Net/RequestStream.cs
System.Net/ResponseStream.cs
Mono.Btls/MonoBtlsX509LookupMono.cs
Mono.Btls/MonoBtlsX509LookupType.cs
Mono.Btls/MonoBtlsX509Name.cs
-Mono.Btls/MonoBtlsX509NameList.cs
Mono.Btls/MonoBtlsX509NameEntryType.cs
Mono.Btls/MonoBtlsX509Purpose.cs
Mono.Btls/MonoBtlsX509Revoked.cs
ReferenceSources/NativeMethods.cs
ReferenceSources/RequestCacheProtocol.cs
ReferenceSources/SettingsSectionInternal.cs
+ReferenceSources/SecureStringHelper.cs
ReferenceSources/Socket.cs
ReferenceSources/SR.cs
ReferenceSources/SRCategoryAttribute.cs
../referencesource/System/net/System/Net/IWebProxyFinder.cs
../referencesource/System/net/System/Net/IWebRequestCreate.cs
../referencesource/System/net/System/Net/NetworkAccess.cs
+../referencesource/System/net/System/Net/NetworkCredential.cs
../referencesource/System/net/System/Net/ProtocolViolationException.cs
../referencesource/System/net/System/Net/TransportContext.cs
../referencesource/System/net/System/Net/TransportType.cs
+../../test-helpers/NunitHelpers.cs
WebMatrix.Data/ConnectionEventArgsTests.cs
WebMatrix.Data/DynamicRecordTests.cs
../WebMatrix.Data/DynamicRecord.cs
+../../test-helpers/NunitHelpers.cs
System.Collections.ObjectModel/ObservableCollectionTest.cs
System.Collections.ObjectModel/ReadOnlyObservableCollectionTest.cs
System.Collections.Specialized/NotifyCollectionChangedEventArgsTest.cs
+++ /dev/null
-using System.Threading;
-using StringMaker = System.Security.Util.Tokenizer.StringMaker;
-
-namespace System
-{
- static class SharedStatics
- {
- static StringMaker shared;
- static public StringMaker GetSharedStringMaker ()
- {
- if (shared == null)
- Interlocked.CompareExchange (ref shared, new StringMaker (), null);
-
- return shared;
- }
-
- static public void ReleaseSharedStringMaker (ref StringMaker maker)
- {
-
- }
- }
-}
\ No newline at end of file
return false;
}
+ [MonoTODO]
+ public static void CleanupUnusedObjectsInCurrentContext ()
+ {
+ if (Environment.IsRunningOnWindows)
+ throw new PlatformNotSupportedException ();
+ }
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static IntPtr AllocCoTaskMem (int cb);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static string PtrToStringUni (IntPtr ptr, int len);
-#if !MOBILE
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static string PtrToStringBSTR (IntPtr ptr);
-#else
- public static string PtrToStringBSTR (IntPtr ptr)
- {
- throw new NotImplementedException ();
- }
-#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ComVisible (true)]
unresolved_algorithms.Add (nameECDsa_2, defaultECDsa);
unresolved_algorithms.Add (nameECDsa_3, defaultECDsa);
+#if MONODROID
+ algorithms.Add (nameSHA1Cng, defaultSHA1);
+ algorithms.Add (nameSHA256Cng, defaultSHA256);
+ algorithms.Add (nameSHA256Provider, defaultSHA256);
+ algorithms.Add (nameSHA384Cng, defaultSHA384);
+ algorithms.Add (nameSHA384Provider, defaultSHA384);
+ algorithms.Add (nameSHA512Cng, defaultSHA512);
+ algorithms.Add (nameSHA512Provider, defaultSHA512);
+#else
unresolved_algorithms.Add (nameSHA1Cng, defaultSHA1Cng);
unresolved_algorithms.Add (nameSHA256Cng, defaultSHA256Cng);
unresolved_algorithms.Add (nameSHA256Provider, defaultSHA256Provider);
unresolved_algorithms.Add (nameSHA384Provider, defaultSHA384Provider);
unresolved_algorithms.Add (nameSHA512Cng, defaultSHA512Cng);
unresolved_algorithms.Add (nameSHA512Provider, defaultSHA512Provider);
+#endif
Dictionary<string,string> oid = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
// comments here are to match with MS implementation (but not with doc)
#region Sync with metadata/object-internals.h
int lock_thread_id;
// stores a thread handle
- internal IntPtr system_thread_handle;
+ IntPtr handle;
+ IntPtr native_handle; // used only on Win32
/* Note this is an opaque object (an array), not a CultureInfo */
private object cached_culture_info;
private IntPtr abort_protected_block_count;
private int priority = (int) ThreadPriority.Normal;
private IntPtr owned_mutex;
+ private IntPtr suspended_event;
/*
* These fields are used to avoid having to increment corlib versions
* when a new field is added to the unmanaged MonoThread structure.
// Closes the system thread handle
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern void Thread_free_internal(IntPtr handle);
+ private extern void Thread_free_internal();
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
~InternalThread() {
- Thread_free_internal(system_thread_handle);
+ Thread_free_internal();
}
}
* of icalls, do not require an increment.
*/
#pragma warning disable 169
- private const int mono_corlib_version = 160;
+ private const int mono_corlib_version = 162;
#pragma warning restore 169
[ComVisible (true)]
using NUnit.Framework;
using Mono;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
-
namespace MonoTests.Mono {
[TestFixture]
using NUnit;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Collections.Concurrent
{
using System.Collections.Concurrent;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Collections.Concurrent
{
public void Constructor_StringMode ()
{
string test = "string-filemode";
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream (test, FileMode.Create);
- CheckCommonDetails (test, isfs, true, true);
+ using (var isfs = new IsolatedStorageFileStream (test, FileMode.Create)) {
+ CheckCommonDetails (test, isfs, true, true);
+ }
}
[Test]
public void Constructor_StringModeAccess ()
{
string test = "string-filemode-fileaccess";
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.ReadWrite);
- CheckCommonDetails (test, isfs, true, true);
+ using (var isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.ReadWrite)) {
+ CheckCommonDetails (test, isfs, true, true);
+ }
}
[Test]
public void Constructor_StringModeAccessShare ()
{
string test = "string-filemode-fileaccess-fileshare";
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.Write, FileShare.Read);
- CheckCommonDetails (test, isfs, false, true);
+ using (var isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.Write, FileShare.Read)) {
+ CheckCommonDetails (test, isfs, false, true);
+ }
}
[Test]
[ExpectedException (typeof (IsolatedStorageException))]
public void Handle ()
{
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream ("handle", FileMode.Create);
- IntPtr p = isfs.Handle;
+ using (var isfs = new IsolatedStorageFileStream ("handle", FileMode.Create)) {
+ IntPtr p = isfs.Handle;
+ }
}
[Test]
public void RootPath ()
{
- new IsolatedStorageFileStream ("/rootpath", FileMode.Create);
+ new IsolatedStorageFileStream ("/rootpath", FileMode.Create).Close ();
}
[Test]
return res.Result;
}
-#if !MOBILE_STATIC
[Test]
+ [Ignore ("Incompatible with nunitlite")]
public void FinishedTaskOnCompleted ()
{
var mres = new ManualResetEvent (false);
mres.Set ();
// this will only terminate correctly if the test was not executed from the main thread
- // e.g. Touch.Unit defaults to run tests on the main thread and this will return false
+ // e.g. nunitlite/Touch.Unit defaults to run tests on the main thread and this will return false
Assert.AreEqual (Thread.CurrentThread.IsBackground, mres2.WaitOne (2000), "#2");;
}
-#endif
-
[Test]
public void CompletionOnSameCustomSynchronizationContext ()
{
}
[Test]
- [Category ("MobileNotWorking")]
public void BSTR_Roundtrip ()
{
string s = "mono";
}
[Test]
- [Category ("MobileNotWorking")]
public void StringToBSTRWithNullValues ()
{
int size = 128;
);
#endif
+#if !MOBILE_STATIC
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public class FourByteStruct
{
return objResult;
}
+#endif
}
#if !MOBILE
[ComImport()]
using System.Security.AccessControl;
using System.Security.Principal;
using NUnit.Framework;
-using NUnit.Framework.SyntaxHelpers;
namespace MonoTests.System.Security.AccessControl {
public void RSASignatureDescription ()
{
// TODO: this would be cleaner with NUnit TestCase'es but they're NUnit 2.5+ :(
-#if FULL_AOT_RUNTIME || MONOTOUCH
+#if FULL_AOT_RUNTIME || MONOTOUCH || MONODROID
RSASignatureDescriptionCore ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "System.Security.Cryptography.SHA1Cng", "System.Security.Cryptography.SHA1CryptoServiceProvider");
RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "System.Security.Cryptography.SHA256Cng", "System.Security.Cryptography.SHA256Managed");
RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "System.Security.Cryptography.SHA384Cng", "System.Security.Cryptography.SHA384Managed");
}
}
-}
\ No newline at end of file
+}
using NUnit.Framework;
using NUnit.Framework.Constraints;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
-
namespace MonoTests.System.Text
{
[TestFixture]
using NUnit.Framework;
using NUnit.Framework.Constraints;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
-
namespace MonoTests.System.Text
{
[TestFixture]
using NUnit.Framework;
using System;
+using System.Reflection;
using System.IO;
using System.Text;
[Category ("MobileNotWorking")]
public void Bug415628 ()
{
- using (var f = File.Open ("Test/resources/415628.bin", FileMode.Open)) {
+ using (var f = File.Open (Path.Combine (Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location), "Test/resources/415628.bin"), FileMode.Open)) {
BinaryReader br = new BinaryReader (f);
byte [] buf = br.ReadBytes (8000);
Encoding.UTF8.GetString(buf);
using System.Threading.Tasks;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Threading.Tasks
{
using System.Collections.Generic;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Threading.Tasks
{
using System.Threading.Tasks;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Threading.Tasks
{
using System.Collections.Generic;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Threading.Tasks
{
using System.Collections.Generic;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
-
namespace MonoTests.System.Threading.Tasks
{
[TestFixture]
using NUnit;
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
namespace MonoTests.System.Threading
{
using NUnit.Framework;
-#if !MOBILE
-using NUnit.Framework.SyntaxHelpers;
-#endif
-
namespace MonoTests.System
{
[TestFixture]
MustTLE (string.Format ("{0}ZZZZ,{1}", typeof (MyRealEnum).FullName, aqn));
}
+ [Test]
+ public void GetTypeExceptionMsg () {
+ string typeName = "system.int32, foo";
+ try {
+ Type.GetType(typeName, true, false);
+ } catch (TypeLoadException ex) {
+ Assert.IsTrue (ex.Message.Contains ("system.int32"));
+ Assert.IsTrue (ex.Message.Contains ("foo"));
+ }
+ }
+
delegate void MyAction<in T>(T ag);
[Test] //bug #668506
}
#endif
+
+ [Test]
+ public void GetTypeBadArity()
+ {
+ // Regression test for #46250
+ try {
+ Type.GetType ("System.Collections.Generic.Dictionary`2[System.String]", true);
+ Assert.Fail ("Did not throw an exception (#1)");
+ } catch (ArgumentException) {
+ }
+
+ try {
+ Type.GetType ("System.Collections.Generic.Dictionary`2[System.String,System.Int32,System.Int64]", true);
+ Assert.Fail ("Did not throw an exception (#2)");
+ } catch (ArgumentException) {
+ }
+ }
+
public abstract class Stream : IDisposable
{
public void Dispose ()
<Compile Include="..\referencesource\mscorlib\system\security\util\parser.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\security\util\tokenizer.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\serializableattribute.cs" />\r
+ <Compile Include="..\referencesource\mscorlib\system\sharedstatics.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\single.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\stackoverflowexception.cs" />\r
<Compile Include="..\referencesource\mscorlib\system\string.cs" />\r
<Compile Include="ReferenceSources\RuntimeHandles.cs" />\r
<Compile Include="ReferenceSources\RuntimeType.cs" />\r
<Compile Include="ReferenceSources\SecurityContext.cs" />\r
- <Compile Include="ReferenceSources\SharedStatics.cs" />\r
<Compile Include="ReferenceSources\String.cs" />\r
<Compile Include="ReferenceSources\TextInfo.cs" />\r
<Compile Include="ReferenceSources\Type.cs" />\r
ReferenceSources/Buffer.cs
ReferenceSources/TextInfo.cs
ReferenceSources/win32native.cs
-ReferenceSources/SharedStatics.cs
ReferenceSources/SecurityContext.cs
ReferenceSources/PathInternal.cs
ReferenceSources/BinaryCompatibility.cs
../referencesource/mscorlib/system/rttype.cs
../referencesource/mscorlib/system/sbyte.cs
../referencesource/mscorlib/system/serializableattribute.cs
+../referencesource/mscorlib/system/sharedstatics.cs
../referencesource/mscorlib/system/stackoverflowexception.cs
../referencesource/mscorlib/system/single.cs
../referencesource/mscorlib/system/string.cs
+../../test-helpers/NunitHelpers.cs
Microsoft.Win32/RegistryKeyTest.cs
Mono/DataConvertTest.cs
../Mono/DataConverter.cs
{
var xml = rootTree.RenderUrl ("T:System.String", generator);
Assert.IsNotNull (xml);
- Assert.IsNotEmpty (xml);
+ AssertHelper.IsNotEmpty (xml);
AssertValidXml (xml);
AssertEcmaFullTypeName (xml, "System.String");
}
{
var xml = rootTree.RenderUrl ("T:System.Int32", generator);
Assert.IsNotNull (xml);
- Assert.IsNotEmpty (xml);
+ AssertHelper.IsNotEmpty (xml);
AssertValidXml (xml);
AssertEcmaFullTypeName (xml, "System.Int32");
}
// HACK: in reality we have currently 4 known issues which are due to duplicated namespaces across
// doc sources, something that was never supported and that we need to improve/fix at some stage
- Assert.LessOrEqual (4, errorCount, errorCount + " / " + testCount.ToString ());
+ AssertHelper.LessOrEqual (4, errorCount, errorCount + " / " + testCount.ToString ());
}
IEnumerable<Node> GetLeaves (Node node)
{
// the docPath variable is the only one we know for sure should exist
Assert.IsNotNull (Config.Get ("docPath"));
- Assert.IsNotEmpty (Config.Get ("docPath"));
+ AssertHelper.IsNotEmpty (Config.Get ("docPath"));
}
}
}
+../../test-helpers/NunitHelpers.cs
Monodoc/HelpSourceTests.cs
Monodoc/EcmaDocTests.cs
Monodoc/TreeTest.cs
// </copyright>
//------------------------------------------------------------------------------
+#if MONO
+#undef FEATURE_PAL
+#endif
+
namespace System.Net {
using System.IO;
/// </devdoc>
public class NetworkCredential : ICredentials,ICredentialsByHost {
+#if FEATURE_MONO_CAS
private static volatile EnvironmentPermission m_environmentUserNamePermission;
private static volatile EnvironmentPermission m_environmentDomainNamePermission;
private static readonly object lockingObject = new object();
+#endif
private string m_domain;
private string m_userName;
#if !FEATURE_PAL
}
#endif //!FEATURE_PAL
+#if FEATURE_MONO_CAS
void InitializePart1() {
if (m_environmentUserNamePermission == null) {
lock(lockingObject) {
}
}
}
-
+#endif
/// <devdoc>
/// <para>
/// </devdoc>
public string UserName {
get {
+#if FEATURE_MONO_CAS
InitializePart1();
m_environmentUserNamePermission.Demand();
+#endif
return InternalGetUserName();
}
set {
/// </devdoc>
public string Password {
get {
+#if FEATURE_MONO_CAS
ExceptionHelper.UnmanagedPermission.Demand();
+#endif
return InternalGetPassword();
}
set {
/// </devdoc>
public SecureString SecurePassword {
get {
+#if FEATURE_MONO_CAS
ExceptionHelper.UnmanagedPermission.Demand();
+#endif
return InternalGetSecurePassword().Copy();
}
set {
/// </devdoc>
public string Domain {
get {
+#if FEATURE_MONO_CAS
InitializePart1();
m_environmentDomainNamePermission.Demand();
+#endif
return InternalGetDomain();
}
set {
internal sealed class SharedStatics
{
+#if MONO
+ // TODO: We are using only GetSharedStringMaker for now which is
+ // ok to be AppDomain static
+ static readonly SharedStatics _sharedStatics = new SharedStatics();
+
+ private SharedStatics()
+ {
+ }
+#else
// this is declared static but is actually forced to be the same object
// for each AppDomain at AppDomain create time.
private static SharedStatics _sharedStatics;
{
BCLDebug.Assert(false, "SharedStatics..ctor() is never called.");
}
+#endif
private volatile String _Remoting_Identity_IDGuid;
public static String Remoting_Identity_IDGuid
--- /dev/null
+using System.IO;
+using System.Collections;
+using NUnit.Framework.Constraints;
+
+namespace NUnit.Framework
+{
+ static class CollectionAssert
+ {
+ public static void DoesNotContain (IEnumerable collection, object val)
+ {
+ Assert.That(collection, Has.No.Member(val));
+ }
+
+ public static void Contains (IEnumerable collection, object val)
+ {
+ Assert.That(collection, Has.Member(val));
+ }
+
+ public static void AreEqual (IEnumerable expected, IEnumerable actual, string message = null, params object[] args)
+ {
+ Assert.That(actual, Is.EqualTo(expected), message, args);
+ }
+
+ public static void AreEquivalent (IEnumerable expected, IEnumerable actual, string message = null, params object[] args)
+ {
+ Assert.That(actual, Is.EquivalentTo(expected), message, args);
+ }
+
+ public static void IsEmpty(IEnumerable collection, string message = null, params object[] args)
+ {
+ Assert.That(collection, new EmptyCollectionConstraint(), message, args);
+ }
+ }
+
+ static class FileAssert
+ {
+ public static void AreEqual(Stream expected, Stream actual, string message, params object[] args)
+ {
+ Assert.That(actual, Is.EqualTo(expected), message, args);
+ }
+
+ public static void AreEqual(string expected, string actual, string message, params object[] args)
+ {
+ using (FileStream exStream = File.OpenRead(expected))
+ using (FileStream acStream = File.OpenRead(actual))
+ {
+ AreEqual(exStream, acStream, message, args);
+ }
+ }
+ }
+
+ static class StringAssert
+ {
+ public static void Contains(string expected, string actual, string message = null, params object[] args)
+ {
+ Assert.That(actual, Is.StringContaining (expected), message, args);
+ }
+
+ public static void StartsWith(string expected, string actual, string message = null, params object[] args)
+ {
+ Assert.IsTrue (actual.StartsWith (expected), message, args);
+ }
+ }
+
+ static class AssertHelper
+ {
+ public static void IsEmpty (string aString, string message = null, params object[] args )
+ {
+ Assert.That(aString, Is.Empty, message, args);
+ }
+
+ public static void IsNotEmpty (string aString, string message = null, params object[] args )
+ {
+ Assert.That(aString, Is.Not.Empty, message, args);
+ }
+
+ public static void Less(int arg1, int arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.LessThan(arg2), message, args);
+ }
+
+ public static void Greater(int arg1, int arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.GreaterThan(arg2), message, args);
+ }
+
+ public static void Greater(double arg1, double arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.GreaterThan(arg2), message, args);
+ }
+
+ public static void GreaterOrEqual(int arg1, int arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args);
+ }
+
+ public static void GreaterOrEqual(long arg1, long arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args);
+ }
+
+ public static void LessOrEqual (int arg1, int arg2, string message = null, params object[] args)
+ {
+ Assert.That(arg1, Is.LessThanOrEqualTo(arg2), message, args);
+ }
+
+ public static void IsNotInstanceOfType(System.Type expected, object actual, string message, params object[] args )
+ {
+ Assert.IsFalse (actual.GetType ().IsInstanceOfType (expected), message, args);
+ }
+ }
+}
+++ /dev/null
-// CS1691: `2' is not a valid warning number
-// Line: 0
-// Compiler options: -warnaserror -warnaserror:1691,2
-
+++ /dev/null
-// CS1691: `20' is not a valid warning number
-// Line: 0
-// Compiler options: -warnaserror -warnaserror-:20
-
+++ /dev/null
-// CS1691: `20' is not a valid warning number
-// Line: 0
-// Compiler options: -warnaserror -nowarn:20
-
+++ /dev/null
-// CS1691: `1' is not a valid warning number
-// Line: 5
-// Compiler options: -warnaserror
-
-#pragma warning disable 1
-
--- /dev/null
+// CS1744: Named argument `p1' cannot be used for a parameter which has positional argument specified
+// Line: 8
+
+internal class Program
+{
+ public static void Main ()
+ {
+ Method (1, 2, p1: 3);
+ }
+
+ static void Method (int p1, int paramNamed, int p2)
+ {
+ }
+
+ static void Method (int p1, int p2, object paramNamed)
+ {
+ }
+}
+++ /dev/null
-// CS1904: `4013' is not a valid warning number
-// Line: 0
-// Compiler options: -nowarn:4014,4013
-
-class ClassMain {
- public static void Main () {}
-}
-
// The slot has been taken by positional argument
if (temp != null && !(temp is NamedArgument))
- break;
+ return NamedArgumentsMismatch - i - 1;
}
if (!arg_moved) {
// Special format which encodes original variable name and
// it's scope to support lifted variables debugging. This
// is same what csc does and allows to correctly set fields
- // scope information (like ambiguity, our of scope, etc).
+ // scope information (like ambiguity, out of scope, etc).
//
var id = rc.CurrentBlock.Explicit.GetDebugSymbolScopeIndex ();
return "<" + local_info.Name + ">__" + id;
method.Block = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc,
ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis);
+
method.Block.AddStatement (new TryFinallyBlockProxyStatement (this, block));
// Cannot it add to storey because it'd be emitted before nested
8009, 8094
};
- static HashSet<int> AllWarningsHashSet;
-
public Report (CompilerContext context, ReportPrinter printer)
{
if (context == null)
- throw new ArgumentNullException ("settings");
+ throw new ArgumentNullException ("context");
if (printer == null)
throw new ArgumentNullException ("printer");
extra_information.Add (msg);
}
- public bool CheckWarningCode (int code, Location loc)
- {
- if (AllWarningsHashSet == null)
- AllWarningsHashSet = new HashSet<int> (AllWarnings);
-
- if (AllWarningsHashSet.Contains (code))
- return true;
-
- Warning (1691, 1, loc, "`{0}' is not a valid warning number", code);
- return false;
- }
-
public void ExtraInformation (Location loc, string msg)
{
extra_information.Add (String.Format ("{0} {1}", loc, msg));
public void WarningDisable (Location location, int code, Report Report)
{
- if (Report.CheckWarningCode (code, location))
- regions.Add (new Disable (location.Row, code));
+ regions.Add (new Disable (location.Row, code));
}
public void WarningEnable (int line)
public void WarningEnable (Location location, int code, CompilerContext context)
{
- if (!context.Report.CheckWarningCode (code, location))
- return;
-
if (context.Settings.IsWarningDisabledGlobally (code))
context.Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code);
public bool ProcessWarningsList (string text, Action<int> action)
{
- bool valid = true;
foreach (string wid in text.Split (numeric_value_separator, StringSplitOptions.RemoveEmptyEntries)) {
var warning = wid;
if (warning.Length == 6 && warning [0] == 'C' && warning [1] == 'S')
continue;
}
- if (report.CheckWarningCode (id, Location.Null)) {
- action (id);
- } else {
- report.Error (1904, "`{0}' is not a valid warning number", wid);
- valid = false;
- }
+ action (id);
}
- return valid;
+ return true;
}
void Error_RequiresArgument (string option)
case "/appconfig":
case "/baseaddress":
case "/deterministic":
+ case "/deterministic+":
+ case "/deterministic-":
case "/errorendlocation":
case "/errorlog":
case "/features":
public override void Emit (EmitContext ec)
{
- if (Parent != null) {
- // TODO: It's needed only when scope has variable (normal or lifted)
- ec.BeginScope (GetDebugSymbolScopeIndex ());
+ // TODO: It's needed only when scope has variable (normal or lifted)
+ var scopeIndex = GetDebugSymbolScopeIndex ();
+ if (scopeIndex > 0) {
+ ec.BeginScope (scopeIndex);
}
EmitScopeInitialization (ec);
DoEmit (ec);
- if (Parent != null)
+ if (scopeIndex > 0)
ec.EndScope ();
if (ec.EmitAccurateDebugInfo && HasReachableClosingBrace && !(this is ParametersBlock) &&
storey.Parent.PartialContainer.AddCompilerGeneratedClass (storey);
}
- public int GetDebugSymbolScopeIndex ()
+ public void DisableDebugScopeIndex ()
+ {
+ debug_scope_index = -1;
+ }
+
+ public virtual int GetDebugSymbolScopeIndex ()
{
if (debug_scope_index == 0)
debug_scope_index = ++ParametersBlock.debug_scope_index;
return res;
}
+ public override int GetDebugSymbolScopeIndex ()
+ {
+ return 0;
+ }
+
public LabeledStatement GetLabel (string name, Block block)
{
//
ec.LoopBegin = ec.DefineLabel ();
ec.LoopEnd = ec.DefineLabel ();
- if (!(Statement is Block))
- ec.BeginCompilerScope (variable.Block.Explicit.GetDebugSymbolScopeIndex ());
+ ec.BeginCompilerScope (variable.Block.Explicit.GetDebugSymbolScopeIndex ());
+ body.Explicit.DisableDebugScopeIndex ();
variable.CreateBuilder (ec);
Statement.Emit (ec);
- if (!(Statement is Block))
- ec.EndScope ();
+ ec.EndScope ();
ec.LoopBegin = old_begin;
ec.LoopEnd = old_end;
</locals>
<scopes>
<entry index="0" start="0x1" end="0x1e" />
- <entry index="1" start="0xb" end="0x11" />
- <entry index="2" start="0xf" end="0x10" />
+ <entry index="1" start="0xf" end="0x10" />
</scopes>
</method>
<method token="0x6000019">
</locals>
<scopes>
<entry index="0" start="0x1" end="0x37" />
- <entry index="1" start="0xe" end="0x18" />
- <entry index="2" start="0x16" end="0x17" />
+ <entry index="1" start="0x16" end="0x17" />
</scopes>
</method>
<method token="0x600001a">
</locals>
<scopes>
<entry index="0" start="0x1" end="0x3c" />
- <entry index="1" start="0xf" end="0x18" />
- <entry index="2" start="0x16" end="0x17" />
+ <entry index="1" start="0x16" end="0x17" />
</scopes>
</method>
<method token="0x600001b">
</locals>
<scopes>
<entry index="0" start="0x1" end="0x4d" />
- <entry index="1" start="0x24" end="0x31" />
- <entry index="2" start="0x2f" end="0x30" />
+ <entry index="1" start="0x2f" end="0x30" />
</scopes>
</method>
</methods>
</sequencepoints>
<locals />
<scopes>
- <entry index="0" start="0x0" end="0xb" />
+ <entry index="0" start="0x0" end="0x0" />
+ <entry index="1" start="0x0" end="0xb" />
</scopes>
</method>
</methods>
</locals>
<scopes>
<entry index="0" start="0x1" end="0x1c" />
- <entry index="1" start="0xb" end="0xf" />
- <entry index="2" start="0x1c" end="0x3f" />
- <entry index="3" start="0x28" end="0x2e" />
+ <entry index="1" start="0x1c" end="0x3f" />
</scopes>
</method>
<method token="0x6000003">
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<symbols>
+ <files>
+ <file id="1" name="test-debug-31.cs" checksum="e1579371d047d82b8d90c0dc26393808" />
+ </files>
+ <methods>
+ <method token="0x6000001">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000002">
+ <sequencepoints>
+ <entry il="0x0" row="8" col="3" file_ref="1" hidden="false" />
+ <entry il="0x1" row="9" col="4" file_ref="1" hidden="false" />
+ <entry il="0x20" row="11" col="4" file_ref="1" hidden="false" />
+ <entry il="0x21" row="11" col="25" file_ref="1" hidden="false" />
+ <entry il="0x2a" row="11" col="13" file_ref="1" hidden="false" />
+ <entry il="0x2e" row="12" col="4" file_ref="1" hidden="false" />
+ <entry il="0x2f" row="13" col="5" file_ref="1" hidden="false" />
+ <entry il="0x30" row="13" col="13" file_ref="1" hidden="false" />
+ <entry il="0x35" row="14" col="4" file_ref="1" hidden="false" />
+ <entry il="0x36" row="11" col="25" file_ref="1" hidden="false" />
+ <entry il="0x43" row="16" col="4" file_ref="1" hidden="false" />
+ <entry il="0x44" row="16" col="26" file_ref="1" hidden="false" />
+ <entry il="0x4f" row="16" col="13" file_ref="1" hidden="false" />
+ <entry il="0x56" row="16" col="33" file_ref="1" hidden="false" />
+ <entry il="0x57" row="17" col="5" file_ref="1" hidden="false" />
+ <entry il="0x59" row="17" col="13" file_ref="1" hidden="false" />
+ <entry il="0x5e" row="18" col="4" file_ref="1" hidden="false" />
+ <entry il="0x5f" row="16" col="26" file_ref="1" hidden="false" />
+ <entry il="0x70" row="20" col="4" file_ref="1" hidden="false" />
+ <entry il="0x71" row="20" col="26" file_ref="1" hidden="false" />
+ <entry il="0x7c" row="20" col="13" file_ref="1" hidden="false" />
+ <entry il="0x83" row="20" col="33" file_ref="1" hidden="false" />
+ <entry il="0x84" row="21" col="5" file_ref="1" hidden="false" />
+ <entry il="0x86" row="21" col="13" file_ref="1" hidden="false" />
+ <entry il="0x8b" row="22" col="4" file_ref="1" hidden="false" />
+ <entry il="0x8c" row="20" col="26" file_ref="1" hidden="false" />
+ <entry il="0x9d" row="23" col="3" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals>
+ <entry name="array" il_index="0" scope_ref="0" />
+ <entry name="item" il_index="1" scope_ref="1" />
+ <entry name="item1" il_index="4" scope_ref="3" />
+ <entry name="item2" il_index="7" scope_ref="5" />
+ </locals>
+ <scopes>
+ <entry index="0" start="0x20" end="0x43" />
+ <entry index="1" start="0x2e" end="0x35" />
+ <entry index="2" start="0x43" end="0x70" />
+ <entry index="3" start="0x56" end="0x5e" />
+ <entry index="4" start="0x70" end="0x9d" />
+ <entry index="5" start="0x83" end="0x8b" />
+ </scopes>
+ </method>
+ </methods>
+</symbols>
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace cp534534
+{
+ class MainClass
+ {
+ public static void Main ()
+ {
+ var array = new string[] { "a", "b", "c" };
+
+ foreach (var item in array)
+ {
+ Console.WriteLine (item);
+ }
+
+ foreach (var item1 in array) {
+ Console.WriteLine (item1);
+ }
+
+ foreach (var item2 in array) {
+ Console.WriteLine (item2);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<symbols>
+ <files>
+ <file id="1" name="test-debug-32.cs" checksum="71a5517624c6bd01871fcb9ae65242b7" />
+ </files>
+ <methods>
+ <method token="0x6000001">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000002">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000003">
+ <sequencepoints>
+ <entry il="0x0" row="19" col="2" file_ref="1" hidden="false" />
+ <entry il="0x1" row="20" col="2" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000004">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000005">
+ <sequencepoints>
+ <entry il="0x27" row="6" col="2" file_ref="1" hidden="false" />
+ <entry il="0x28" row="7" col="3" file_ref="1" hidden="false" />
+ <entry il="0x43" row="9" col="3" file_ref="1" hidden="false" />
+ <entry il="0x4a" row="10" col="3" file_ref="1" hidden="false" />
+ <entry il="0x59" row="10" col="7" file_ref="1" hidden="false" />
+ <entry il="0x5a" row="11" col="4" file_ref="1" hidden="false" />
+ <entry il="0x7c" row="12" col="3" file_ref="1" hidden="false" />
+ <entry il="0x8d" row="16" col="2" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals />
+ <scopes>
+ <entry index="0" start="0x59" end="0x7c" />
+ </scopes>
+ </method>
+ <method token="0x6000006">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000007">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000008">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000009">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x600000a">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x600000b">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x600000c">
+ <sequencepoints>
+ <entry il="0x0" row="12" col="13" file_ref="1" hidden="false" />
+ <entry il="0x1" row="13" col="4" file_ref="1" hidden="false" />
+ <entry il="0xd" row="13" col="16" file_ref="1" hidden="false" />
+ <entry il="0xe" row="14" col="4" file_ref="1" hidden="false" />
+ <entry il="0xf" row="15" col="3" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals />
+ <scopes>
+ <entry index="0" start="0x0" end="0x0" />
+ <entry index="1" start="0x0" end="0xf" />
+ <entry index="2" start="0xd" end="0xe" />
+ </scopes>
+ </method>
+ </methods>
+</symbols>
\ No newline at end of file
--- /dev/null
+using System.Collections.Generic;
+
+class X
+{
+ internal static IEnumerable<int> EnumerateKind ()
+ {
+ yield return 1;
+
+ int h = 3;
+ try {
+ yield return h;
+ } finally {
+ if (h != 1) {
+ }
+ }
+ }
+
+ public static void Main ()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+internal class Program
+{
+ public static void Main ()
+ {
+ Method (1, 2, paramNamed: 3);
+ }
+
+ static void Method (int p1, int paramNamed, int p2)
+ {
+ throw new ApplicationException ();
+ }
+
+ static void Method (int p1, int p2, object paramNamed)
+ {
+ }
+}
</method>
</type>
</test>
+ <test name="test-debug-31.cs">
+ <type name="cp534534.MainClass">
+ <method name="Void Main()" attrs="150">
+ <size>158</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-debug-32.cs">
+ <type name="X">
+ <method name="System.Collections.Generic.IEnumerable`1[System.Int32] EnumerateKind()" attrs="147">
+ <size>23</size>
+ </method>
+ <method name="Void Main()" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<EnumerateKind>c__Iterator0">
+ <method name="Boolean MoveNext()" attrs="486">
+ <size>152</size>
+ </method>
+ <method name="Int32 System.Collections.Generic.IEnumerator<int>.get_Current()" attrs="2529">
+ <size>14</size>
+ </method>
+ <method name="System.Object System.Collections.IEnumerator.get_Current()" attrs="2529">
+ <size>19</size>
+ </method>
+ <method name="Void Dispose()" attrs="486">
+ <size>57</size>
+ </method>
+ <method name="Void Reset()" attrs="486">
+ <size>6</size>
+ </method>
+ <method name="System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()" attrs="481">
+ <size>14</size>
+ </method>
+ <method name="System.Collections.Generic.IEnumerator`1[System.Int32] System.Collections.Generic.IEnumerable<int>.GetEnumerator()" attrs="481">
+ <size>26</size>
+ </method>
+ <method name="Void <>__Finally0()" attrs="129">
+ <size>17</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-decl-expr-01.cs">
<type name="DeclarationExpression">
<method name="Int32 Main()" attrs="150">
</method>
</type>
</test>
+ <test name="test-named-10.cs">
+ <type name="Program">
+ <method name="Void Main()" attrs="150">
+ <size>15</size>
+ </method>
+ <method name="Void Method(Int32, Int32, Int32)" attrs="145">
+ <size>7</size>
+ </method>
+ <method name="Void Method(Int32, Int32, System.Object)" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-nameof-01.cs">
<type name="X">
<method name="Int32 Main()" attrs="150">
<Reference Include="System" />\r
<Reference Include="System.Core" />\r
<Reference Include="System.Xml" />\r
- <Reference Include="Mono.Cecil">\r
- <HintPath>..\..\class\lib\net_4_x\Mono.Cecil.dll</HintPath>\r
- </Reference>\r
</ItemGroup>\r
<ItemGroup>\r
<Compile Include="AssemblyResolver.cs" />\r
<Compile Include="..\..\class\Mono.Options\Mono.Options\Options.cs">\r
<Link>Options.cs</Link>\r
</Compile>\r
+\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil.Cil\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil.Metadata\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil.PE\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ArrayType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyFlags.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyHashAlgorithm.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyLinkedResource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyNameDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyNameReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyReader.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyWriter.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\BaseAssemblyResolver.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\CallSite.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\CustomAttribute.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\DefaultAssemblyResolver.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EmbeddedResource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EventAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EventDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EventReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ExportedType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FieldAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FieldDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FieldReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FileAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FunctionPointerType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericInstanceMethod.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericInstanceType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericParameter.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericParameterAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IConstantProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ICustomAttributeProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IGenericInstance.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IGenericParameterProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMarshalInfoProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMemberDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMetadataScope.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMetadataTokenProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMethodSignature.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Import.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\LinkedResource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ManifestResourceAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MarshalInfo.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MemberDefinitionCollection.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MemberReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MetadataResolver.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MetadataSystem.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodCallingConvention.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodImplAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodReturnType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodSemanticsAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodSpecification.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Modifiers.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ModuleDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ModuleKind.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ModuleReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\NativeType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterDefinitionCollection.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PinnedType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PInvokeAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PInvokeInfo.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PointerType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PropertyAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PropertyDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PropertyReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ReferenceType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Resource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\SecurityDeclaration.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\SentinelType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TargetRuntime.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Treatments.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeDefinitionCollection.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeParser.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeSpecification.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeSystem.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\VariantType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\WindowsRuntimeProjections.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Collections.Generic\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Security.Cryptography\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono\*.cs" /> \r
</ItemGroup>\r
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
find Mono.Linker.Tests -name "*.cs" > Mono.Linker.Tests.dll.sources
Mono.Linker.Tests.dll: Mono.Cecil.dll monolinker.exe Mono.Linker.Tests.dll.sources
- $(MCS) /target:library /out:Mono.Linker.Tests.dll /r:nunit.framework.dll /r:Mono.Cecil.dll /r:monolinker.exe @Mono.Linker.Tests.dll.sources
+ $(MCS) /target:library /out:Mono.Linker.Tests.dll /r:nunitlite.dll /r:Mono.Cecil.dll /r:monolinker.exe @Mono.Linker.Tests.dll.sources
clean:
rm -rf Mono.Cecil.dll monolinker.exe Mono.Linker.Tests.dll.sources Mono.Linker.Tests.dll
SUBDIRS =
include ../../build/rules.make
-LIB_REFS = Mono.Cecil System.Xml System.Core System System.Xml.Linq
+LIB_REFS = System.Xml System.Core System System.Xml.Linq
LOCAL_MCS_FLAGS =
PROGRAM = mono-api-html.exe
<Project>{2CA6026B-2DC8-4C4C-A12C-1E8234049DB7}</Project>\r
<Name>corlib-net_4_x</Name>\r
</ProjectReference>\r
- <ProjectReference Include="../../class/legacy/Mono.Cecil/Mono.Cecil-net_4_x.csproj">\r
- <Project>{6DE38817-EC25-433A-AE58-0D30C5E6C460}</Project>\r
- <Name>Mono.Cecil-net_4_x</Name>\r
- </ProjectReference>\r
<ProjectReference Include="../../class/System.XML/System.Xml-net_4_x.csproj">\r
<Project>{87FD2F0F-5222-4AE6-BD63-2D4975E11E5B}</Project>\r
<Name>System.Xml-net_4_x</Name>\r
--- /dev/null
+//
+// BabysitterSupport.cs: Nunit extensions to support test harness used by Mono.
+// See scripts/babysitter in Mono repository.
+//
+// Author:
+// Andi McClure (andi.mcclure@xamarin.com)
+//
+// Copyright (C) 2015 Xamarin, Inc (http://www.xamarin.com)
+//
+
+namespace Xamarin
+{
+ using System;
+ using System.IO;
+ using System.Collections.Generic;
+ using NUnit.Framework.Api;
+ using NUnit.Framework.Internal;
+ using NUnit.Framework.Internal.Filters;
+
+ public class BabysitterSupport
+ {
+ enum OverrideMode {None, Run, Exclude};
+ public static Dictionary<string, bool> OverrideTests = new Dictionary<string, bool>();
+ private static OverrideMode Override = OverrideMode.None;
+ private static string CurrentTestFile = null, RanTestFile = null, FailedTestFile = null;
+
+ private static void DeleteFile(string path)
+ {
+ try {
+ File.Delete(path);
+ } catch (Exception) {}
+ }
+ private static void WriteFile(string path, string contents)
+ {
+ DeleteFile(path);
+ File.AppendAllText(path, contents);
+ }
+
+ // Environment variables are available from process start, so safe to do setup in a static constructor
+ static BabysitterSupport()
+ {
+ string overrideModeString = Environment.GetEnvironmentVariable("MONO_BABYSITTER_NUNIT_RUN_MODE");
+ string overrideTestString = Environment.GetEnvironmentVariable("MONO_BABYSITTER_NUNIT_RUN_TEST");
+ if (overrideModeString == "RUN")
+ Override = OverrideMode.Run;
+ else if (overrideModeString == "EXCLUDE")
+ Override = OverrideMode.Exclude;
+ if (Override != OverrideMode.None)
+ {
+ string[] overrideTests = overrideTestString.Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries);
+ foreach (string s in overrideTests)
+ OverrideTests[s] = true;
+ }
+
+ CurrentTestFile = Environment.GetEnvironmentVariable("MONO_BABYSITTER_NUNIT_CURRENT_TEST_FILE");
+ RanTestFile = Environment.GetEnvironmentVariable("MONO_BABYSITTER_NUNIT_RAN_TEST_FILE");
+ FailedTestFile = Environment.GetEnvironmentVariable("MONO_BABYSITTER_NUNIT_FAILED_TEST_FILE");
+ }
+
+ // Entry points
+
+ public static void RecordEnterTest( string testName )
+ {
+ if (CurrentTestFile != null)
+ WriteFile(CurrentTestFile, testName);
+ if (RanTestFile != null)
+ File.AppendAllText(RanTestFile, testName + Environment.NewLine);
+ }
+
+ public static void RecordLeaveTest( string testName )
+ {
+ if (CurrentTestFile != null)
+ DeleteFile(CurrentTestFile);
+ }
+
+ public static void RecordFailedTest( string testName )
+ {
+ if (FailedTestFile != null)
+ File.AppendAllText(FailedTestFile, testName + Environment.NewLine);
+ }
+
+ public static ITestFilter AddBabysitterFilter(ITestFilter currentFilter)
+ {
+ if (Override == OverrideMode.None)
+ return currentFilter;
+ return new AndFilter(currentFilter, new BabysitterFilter());
+ }
+
+ [Serializable]
+ private class BabysitterFilter : TestFilter
+ {
+ public override bool Match(ITest test)
+ {
+ if (test.IsSuite) // A suite returning true will automatically run ALL contents, filters ignored
+ return false;
+ bool inList = OverrideTests.ContainsKey(test.FullName);
+ bool allow = true;
+ switch (Override)
+ {
+ case OverrideMode.None:
+ break;
+ case OverrideMode.Run:
+ allow = inList;
+ break;
+ case OverrideMode.Exclude:
+ allow = !inList;
+ break;
+ }
+ return allow;
+ }
+ }
+ }
+}
\ No newline at end of file
../../../../external/nunit-lite/NUnitLite-1.0.0/src/framework/TestCaseData.cs
../../../../external/nunit-lite/NUnitLite-1.0.0/src/framework/TestContext.cs
../../../../external/nunit-lite/NUnitLite-1.0.0/src/framework/Throws.cs
+BabysitterSupport.cs
+++ /dev/null
-<?xml version="1.0" encoding="Windows-1252"?>\r
-<configuration>\r
- <runtime>\r
- <!-- \r
- This is necessary to prevent the runner from terminating on\r
- any unhandled exceptions which occur. We account for unhandled exceptions on\r
- other threads with an event handler, but would still be terminated using the\r
- new behavior.\r
- -->\r
- <legacyUnhandledExceptionPolicy enabled="1" />\r
- </runtime>\r
-</configuration>\r
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<configuration>\r
+ <!-- __INSERT_CUSTOM_APP_CONFIG_GLOBAL__ -->\r
+ <runtime>\r
+ <!-- \r
+ This is necessary to prevent the runner from terminating on\r
+ any unhandled exceptions which occur. We account for unhandled exceptions on\r
+ other threads with an event handler, but would still be terminated using the\r
+ new behavior.\r
+ -->\r
+ <legacyUnhandledExceptionPolicy enabled="1" />\r
+ <!-- __INSERT_CUSTOM_APP_CONFIG_RUNTIME__ -->\r
+ </runtime>\r
+</configuration>\r
EXTRA_DISTFILES = \
data/xbuild.rsp \
data/xbuild.exe.config.in \
+ data/xbuild.exe.config_test.in \
data/Microsoft.Build.xsd \
data/2.0/Microsoft.Common.tasks \
data/3.5/Microsoft.Common.tasks \
--- /dev/null
+ <generatePublisherEvidence enabled="false" />
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-100.0.0.0" newVersion="@ASM_VERSION@" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Build.Engine" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-100.0.0.0" newVersion="@ASM_VERSION@" />
+ </dependentAssembly>
+ </assemblyBinding>
ifeq (4.0, $(FRAMEWORK_VERSION))
NO_TEST=true
else
-test-local: copy-targets $(test_lib).config
+test-local: copy-targets Test/test-config-file-$(PROFILE)
clean-local: clean-targets clean-test-config
endif
@echo "The net_4_0 profile contains reference assemblies only and cannot be installed/tested as an xbuild toolset"
@exit 1
-$(test_lib).config: $(XBUILD_DATA_DIR)/xbuild.exe.config.in
- sed -e 's/@ASM_VERSION@/$(XBUILD_ASSEMBLY_VERSION)/g' $(XBUILD_DATA_DIR)/xbuild.exe.config.in > $(test_lib).config
+Test/test-config-file-$(PROFILE): $(XBUILD_DATA_DIR)/xbuild.exe.config_test.in
+ sed -e 's/@ASM_VERSION@/$(XBUILD_ASSEMBLY_VERSION)/g' $(XBUILD_DATA_DIR)/xbuild.exe.config_test.in > Test/test-config-file-$(PROFILE)
clean-test-config:
- rm -f $(test_lib).config
+ rm -f Test/test-config-file-$(PROFILE)
copy-targets: copy-targets-$(XBUILD_VERSION)
btls-ssl-ctx.h
btls-ssl.c
btls-ssl.h
+ btls-time64.c
btls-util.c
btls-util.h
btls-x509-chain.c
btls-x509.c
btls-x509.h
- btls-android-utils.c
-
${BORINGSSL_OBJECTS}
)
-EXTRA_DIST = btls-android-utils.c \
+EXTRA_DIST = \
btls-bio.c \
btls-bio.h \
btls-error.c \
btls-ssl-ctx.c \
btls-ssl-ctx.h \
btls-ssl.h \
+ btls-time64.c \
btls-util.c \
btls-util.h \
btls-x509.c \
-rm -rf build-shared
install-exec-local:
- $(install_sh) build-shared/libmono-btls-shared.* "$(DESTDIR)/$(libdir)"
+ $(mkinstalldirs) "$(DESTDIR)$(libdir)"
+ $(install_sh) build-shared/libmono-btls-shared.* "$(DESTDIR)$(libdir)"
+++ /dev/null
-// Copied from Chromium: https://src.chromium.org/svn/trunk/src/base/os_compat_android.cc
-
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#if defined(__ANDROID__)
-
-#include <asm/unistd.h>
-#include <errno.h>
-#include <math.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-
-#if !defined(__LP64__)
-#include <time64.h>
-#endif
-
-#if !defined(__LP64__)
-// 32-bit Android has only timegm64() and not timegm().
-// We replicate the behaviour of timegm() when the result overflows time_t.
-time_t timegm(struct tm* const t) {
- // time_t is signed on Android.
- static const time_t kTimeMax = ~(1L << (sizeof(time_t) * CHAR_BIT - 1));
- static const time_t kTimeMin = (1L << (sizeof(time_t) * CHAR_BIT - 1));
- time64_t result = timegm64(t);
- if (result < kTimeMin || result > kTimeMax)
- return -1;
- return result;
-}
-#endif
-
-#endif
return mono->write_func (mono->instance, in, inl);
}
-static long
-mono_ctrl (BIO *bio, int cmd, long num, void *ptr)
+static int64_t
+mono_ctrl (BIO *bio, int cmd, int64_t num, void *ptr)
{
MonoBtlsBio *mono = (MonoBtlsBio *)bio->ptr;
typedef int (* MonoBtlsReadFunc) (const void *instance, const void *buf, int size, int *wantMore);
typedef int (* MonoBtlsWriteFunc) (const void *instance, const void *buf, int size);
-typedef long (* MonoBtlsControlFunc) (const void *instance, MonoBtlsControlCommand command, long arg);
+typedef int64_t (* MonoBtlsControlFunc) (const void *instance, MonoBtlsControlCommand command, int64_t arg);
BIO *
mono_btls_bio_mono_new (void);
--- /dev/null
+/*
+
+Copyright (c) 2007-2008 Michael G Schwern
+
+This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
+
+The MIT License:
+
+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.
+
+*/
+
+/* See http://code.google.com/p/y2038 for this code's origin */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+/* Spec says except for stftime() and the _r() functions, these
+ all return static memory. Stabbings! */
+static struct tm Static_Return_Date;
+static char Static_Return_String[35];
+
+static const int days_in_month[2][12] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+};
+
+static const int julian_days_by_month[2][12] = {
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335},
+};
+
+static char const wday_name[7][3] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+static char const mon_name[12][3] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static const int length_of_year[2] = { 365, 366 };
+
+/* Some numbers relating to the gregorian cycle */
+static const int64_t years_in_gregorian_cycle = 400;
+#define days_in_gregorian_cycle ((365 * 400) + 100 - 4 + 1)
+static const int64_t seconds_in_gregorian_cycle = days_in_gregorian_cycle * 60LL * 60LL * 24LL;
+
+/* Year range we can trust the time funcitons with */
+#define MAX_SAFE_YEAR 2037
+#define MIN_SAFE_YEAR 1971
+
+/* 28 year Julian calendar cycle */
+#define SOLAR_CYCLE_LENGTH 28
+
+/* Year cycle from MAX_SAFE_YEAR down. */
+static const int safe_years_high[SOLAR_CYCLE_LENGTH] = {
+ 2016, 2017, 2018, 2019,
+ 2020, 2021, 2022, 2023,
+ 2024, 2025, 2026, 2027,
+ 2028, 2029, 2030, 2031,
+ 2032, 2033, 2034, 2035,
+ 2036, 2037, 2010, 2011,
+ 2012, 2013, 2014, 2015
+};
+
+/* Year cycle from MIN_SAFE_YEAR up */
+static const int safe_years_low[SOLAR_CYCLE_LENGTH] = {
+ 1996, 1997, 1998, 1971,
+ 1972, 1973, 1974, 1975,
+ 1976, 1977, 1978, 1979,
+ 1980, 1981, 1982, 1983,
+ 1984, 1985, 1986, 1987,
+ 1988, 1989, 1990, 1991,
+ 1992, 1993, 1994, 1995,
+};
+
+/* Let's assume people are going to be looking for dates in the future.
+ Let's provide some cheats so you can skip ahead.
+ This has a 4x speed boost when near 2008.
+*/
+/* Number of days since epoch on Jan 1st, 2008 GMT */
+#define CHEAT_DAYS (1199145600 / 24 / 60 / 60)
+#define CHEAT_YEARS 108
+
+#define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0)
+#define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a))
+
+/* timegm() is not in the C or POSIX spec, but it is such a useful
+ extension I would be remiss in leaving it out. Also I need it
+ for localtime64()
+*/
+int64_t btls_timegm64(const struct tm *date) {
+ int64_t days = 0;
+ int64_t seconds = 0;
+ int64_t year;
+ int64_t orig_year = (int64_t)date->tm_year;
+ int cycles = 0;
+
+ if( orig_year > 100 ) {
+ cycles = (orig_year - 100) / 400;
+ orig_year -= cycles * 400;
+ days += (int64_t)cycles * days_in_gregorian_cycle;
+ }
+ else if( orig_year < -300 ) {
+ cycles = (orig_year - 100) / 400;
+ orig_year -= cycles * 400;
+ days += (int64_t)cycles * days_in_gregorian_cycle;
+ }
+
+ if( orig_year > 70 ) {
+ year = 70;
+ while( year < orig_year ) {
+ days += length_of_year[IS_LEAP(year)];
+ year++;
+ }
+ }
+ else if ( orig_year < 70 ) {
+ year = 69;
+ do {
+ days -= length_of_year[IS_LEAP(year)];
+ year--;
+ } while( year >= orig_year );
+ }
+
+
+ days += julian_days_by_month[IS_LEAP(orig_year)][date->tm_mon];
+ days += date->tm_mday - 1;
+
+ seconds = days * 60 * 60 * 24;
+
+ seconds += date->tm_hour * 60 * 60;
+ seconds += date->tm_min * 60;
+ seconds += date->tm_sec;
+
+ return(seconds);
+}
#include <btls-util.h>
#include <assert.h>
-#include <time.h>
-
-#if defined(__ANDROID__) && !defined(__LP64__)
-#include <time64.h>
-extern time_t timegm (struct tm* const t);
-#endif
+// #include <time.h>
extern int asn1_generalizedtime_to_tm (struct tm *tm, const ASN1_GENERALIZEDTIME *d);
+extern int64_t btls_timegm64 (const struct tm *date);
+
+
MONO_API void
mono_btls_free (void *data)
{
OPENSSL_free (data);
}
-long
+int64_t
mono_btls_util_asn1_time_to_ticks (ASN1_TIME *time)
{
ASN1_GENERALIZEDTIME *gtime;
struct tm tm;
- time_t epoch;
+ int64_t epoch;
+ int ret;
+
+ memset (&tm, 0, sizeof (tm));
gtime = ASN1_TIME_to_generalizedtime (time, NULL);
- asn1_generalizedtime_to_tm (&tm, gtime);
+ ret = asn1_generalizedtime_to_tm (&tm, gtime);
ASN1_GENERALIZEDTIME_free (gtime);
- epoch = timegm(&tm);
+ epoch = btls_timegm64 (&tm);
return epoch;
}
void
mono_btls_free (void *data);
-long
+int64_t
mono_btls_util_asn1_time_to_ticks (ASN1_TIME *time);
int
return mono_btls_x509_revoked_new (crl, revoked);
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_crl_get_last_update (MonoBtlsX509Crl *crl)
{
return mono_btls_util_asn1_time_to_ticks (X509_CRL_get_lastUpdate (crl->crl));
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_crl_get_next_update (MonoBtlsX509Crl *crl)
{
return mono_btls_util_asn1_time_to_ticks (X509_CRL_get_nextUpdate (crl->crl));
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_crl_get_version (MonoBtlsX509Crl *crl)
{
return X509_CRL_get_version (crl->crl);
MonoBtlsX509Revoked *
mono_btls_x509_crl_get_revoked (MonoBtlsX509Crl *crl, int index);
-long
+int64_t
mono_btls_x509_crl_get_last_update (MonoBtlsX509Crl *crl);
-long
+int64_t
mono_btls_x509_crl_get_next_update (MonoBtlsX509Crl *crl);
-long
+int64_t
mono_btls_x509_crl_get_version (MonoBtlsX509Crl *crl);
MonoBtlsX509Name *
}
static int
-mono_lookup_ctrl (X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret)
+mono_lookup_ctrl (X509_LOOKUP *ctx, int cmd, const char *argp, int64_t argl, char **ret)
{
MonoLookup *lookup = (MonoLookup*)ctx->method_data;
MonoBtlsX509LookupMono *mono = (MonoBtlsX509LookupMono*)argp;
return X509_NAME_oneline (name->name, buffer, size) != NULL;
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_name_hash (MonoBtlsX509Name *name)
{
return X509_NAME_hash (name->name);
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_name_hash_old (MonoBtlsX509Name *name)
{
return X509_NAME_hash_old (name->name);
int
mono_btls_x509_name_get_raw_data (MonoBtlsX509Name *name, void **buffer, int use_canon_enc);
-long
+int64_t
mono_btls_x509_name_hash (MonoBtlsX509Name *name);
-long
+int64_t
mono_btls_x509_name_hash_old (MonoBtlsX509Name *name);
int
return serial->length;
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_revoked_get_revocation_date (MonoBtlsX509Revoked *revoked)
{
ASN1_TIME *date;
int
mono_btls_x509_revoked_get_serial_number (MonoBtlsX509Revoked *revoked, char *buffer, int size);
-long
+int64_t
mono_btls_x509_revoked_get_revocation_date (MonoBtlsX509Revoked *revoked);
int
return X509_VERIFY_PARAM_set1_host (param->param, host, namelen);
}
-MONO_API unsigned long
+MONO_API uint64_t
mono_btls_x509_verify_param_get_flags (MonoBtlsX509VerifyParam *param)
{
return X509_VERIFY_PARAM_get_flags (param->param);
}
MONO_API int
-mono_btls_x509_verify_param_set_flags (MonoBtlsX509VerifyParam *param, unsigned long flags)
+mono_btls_x509_verify_param_set_flags (MonoBtlsX509VerifyParam *param, uint64_t flags)
{
if (!param->owns)
return -1;
mono_btls_x509_verify_param_get_mono_flags (MonoBtlsX509VerifyParam *param)
{
MonoBtlsX509VerifyFlags current;
- unsigned long flags;
+ uint64_t flags;
if (!param->owns)
return -1;
MONO_API int
mono_btls_x509_verify_param_set_mono_flags (MonoBtlsX509VerifyParam *param, MonoBtlsX509VerifyFlags flags)
{
- unsigned long current;
+ uint64_t current;
if (!param->owns)
return -1;
}
MONO_API int
-mono_btls_x509_verify_param_set_time (MonoBtlsX509VerifyParam *param, long time)
+mono_btls_x509_verify_param_set_time (MonoBtlsX509VerifyParam *param, int64_t time)
{
if (!param->owns)
return -1;
int
mono_btls_x509_verify_param_add_host (MonoBtlsX509VerifyParam *param, const char *host, int namelen);
-unsigned long
+uint64_t
mono_btls_x509_verify_param_get_flags (MonoBtlsX509VerifyParam *param);
int
-mono_btls_x509_verify_param_set_flags (MonoBtlsX509VerifyParam *param, unsigned long flags);
+mono_btls_x509_verify_param_set_flags (MonoBtlsX509VerifyParam *param, uint64_t flags);
MonoBtlsX509VerifyFlags
mono_btls_x509_verify_param_get_mono_flags (MonoBtlsX509VerifyParam *param);
mono_btls_x509_verify_param_set_depth (MonoBtlsX509VerifyParam *param, int depth);
int
-mono_btls_x509_verify_param_set_time (MonoBtlsX509VerifyParam *param, long time);
+mono_btls_x509_verify_param_set_time (MonoBtlsX509VerifyParam *param, int64_t time);
char *
mono_btls_x509_verify_param_get_peername (MonoBtlsX509VerifyParam *param);
return SHA_DIGEST_LENGTH;
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_get_not_before (X509 *x509)
{
return mono_btls_util_asn1_time_to_ticks (X509_get_notBefore (x509));
}
-MONO_API long
+MONO_API int64_t
mono_btls_x509_get_not_after (X509 *x509)
{
return mono_btls_util_asn1_time_to_ticks (X509_get_notAfter (x509));
int
mono_btls_x509_get_hash (X509 *x509, const void **data);
-long
+int64_t
mono_btls_x509_get_not_before (X509 *x509);
-long
+int64_t
mono_btls_x509_get_not_after (X509 *x509);
int
esname = get_escaped_class_name (c);
- if (c->generic_class) {
- MonoGenericClass *gclass = c->generic_class;
+ if (mono_class_is_ginst (c)) {
+ MonoGenericClass *gclass = mono_class_get_generic_class (c);
MonoGenericInst *inst = gclass->context.class_inst;
GString *str = g_string_new ("");
int i;
case 4: /* TypeSpec */
klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, (MonoGenericContext *) container);
g_assert (klass);
- return klass->generic_class ? klass->generic_class->container_class->generic_container : NULL;
+ return mono_class_is_ginst (klass) ? mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class) : NULL;
}
g_assert_not_reached ();
return NULL;
MonoMethod *mh = NULL;
mh = mono_get_method_checked (m, decl, NULL, (MonoGenericContext *) container, &error);
- if (mh && (mh->klass && (mh->klass->generic_class || mh->klass->generic_container))) {
+ if (mh && (mh->klass && (mono_class_is_ginst (mh->klass) || mono_class_is_gtd (mh->klass)))) {
char *meth_str;
char *ret;
libwapiincludedir = $(includedir)/mono-$(API_VER)/mono/io-layer
OTHER_H = \
- access.h \
context.h \
error.h \
io.h \
io-portability.h \
macros.h \
messages.h \
- processes.h \
security.h \
sockets.h \
status.h \
wapi-remap.h
OTHER_SRC = \
- access.h \
context.c \
context.h \
error.c \
messages.c \
messages.h \
posix.c \
- processes.c \
- processes.h \
- process-private.h \
security.c \
security.h \
sockets.c \
status.h \
timefuncs.c \
timefuncs.h \
- timefuncs-private.h \
types.h \
uglify.h \
versioninfo.c \
+++ /dev/null
-/*
- * access.h: Access control definitions
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_ACCESS_H_
-#define _WAPI_ACCESS_H_
-
-#include <glib.h>
-
-#include <mono/io-layer/wapi.h>
-
-#define SYNCHRONIZE 0x00100000
-#define STANDARD_RIGHTS_REQUIRED 0x000f0000
-
-#endif /* _WAPI_ACCESS_H_ */
#include "mono/io-layer/wapi.h"
#include "mono/io-layer/wapi-private.h"
-#include "mono/utils/mono-once.h"
+#include "mono/utils/mono-lazy-init.h"
static pthread_key_t error_key;
-static mono_once_t error_key_once=MONO_ONCE_INIT;
+static mono_lazy_init_t error_key_once = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
static void error_init(void)
{
g_assert (ret == 0);
}
-void _wapi_error_cleanup (void)
+static void error_cleanup (void)
{
int ret;
g_assert (ret == 0);
}
+void _wapi_error_cleanup (void)
+{
+ mono_lazy_cleanup (&error_key_once, error_cleanup);
+}
+
/**
* GetLastError:
*
if (_wapi_has_shut_down)
return 0;
- mono_once(&error_key_once, error_init);
+ mono_lazy_initialize(&error_key_once, error_init);
errptr=pthread_getspecific(error_key);
err=GPOINTER_TO_UINT(errptr);
if (_wapi_has_shut_down)
return;
/* Set the thread-local error code */
- mono_once(&error_key_once, error_init);
+ mono_lazy_initialize(&error_key_once, error_init);
ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code));
g_assert (ret == 0);
}
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/timefuncs-private.h>
+#include <mono/io-layer/timefuncs.h>
#include <mono/io-layer/io-portability.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/strenc.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
/*
* If SHM is disabled, this will point to a hash of _WapiFileShare structures, otherwise
#include <mono/io-layer/io-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
gboolean
_wapi_lock_file_region (int fd, off_t offset, off_t length)
#include <mono/io-layer/io-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
static guint32
convert_from_flags(int flags)
+++ /dev/null
-/*
- * process-private.h: Private definitions for process handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#ifndef _WAPI_PROCESS_PRIVATE_H_
-#define _WAPI_PROCESS_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/utils/mono-os-semaphore.h>
-
-/* There doesn't seem to be a defined symbol for this */
-#define _WAPI_PROCESS_CURRENT (gpointer)0xFFFFFFFF
-
-/*
- * Handles > _WAPI_PROCESS_UNHANDLED are pseudo handles which represent processes
- * not started by the runtime.
- */
-/* This marks a system process that we don't have a handle on */
-/* FIXME: Cope with PIDs > sizeof guint */
-#define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1))
-#define _WAPI_PROCESS_UNHANDLED_PID_MASK (-1 & ~_WAPI_PROCESS_UNHANDLED)
-#define WAPI_IS_PSEUDO_PROCESS_HANDLE(handle) ((GPOINTER_TO_UINT(handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED)
-#define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid))
-#define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED)
-
-void _wapi_processes_init (void);
-extern gpointer _wapi_process_duplicate (void);
-extern void wapi_processes_cleanup (void);
-
-/*
- * MonoProcess describes processes we create.
- * It contains a semaphore that can be waited on in order to wait
- * for process termination. It's accessed in our SIGCHLD handler,
- * when status is updated (and pid cleared, to not clash with
- * subsequent processes that may get executed).
- */
-struct MonoProcess {
- pid_t pid; /* the pid of the process. This value is only valid until the process has exited. */
- MonoSemType exit_sem; /* this semaphore will be released when the process exits */
- int status; /* the exit status */
- gint32 handle_count; /* the number of handles to this mono_process instance */
- /* we keep a ref to the creating _WapiHandle_process handle until
- * the process has exited, so that the information there isn't lost.
- */
- gpointer handle;
- gboolean freeable;
- struct MonoProcess *next;
-};
-
-typedef struct MonoProcess MonoProcess;
-
-/*
- * _WapiHandle_process is a structure containing all the required information
- * for process handling.
- */
-struct _WapiHandle_process
-{
- pid_t id;
- guint32 exitstatus;
- gpointer main_thread;
- WapiFileTime create_time;
- WapiFileTime exit_time;
- char *proc_name;
- size_t min_working_set;
- size_t max_working_set;
- gboolean exited;
- struct MonoProcess *mono_process;
-};
-
-typedef struct _WapiHandle_process WapiHandle_process;
-
-#endif /* _WAPI_PROCESS_PRIVATE_H_ */
+++ /dev/null
-/*
- * processes.c: Process handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2011 Novell, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <pthread.h>
-#include <sched.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <sys/time.h>
-#include <fcntl.h>
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <ctype.h>
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-
-/* sys/resource.h (for rusage) is required when using osx 10.3 (but not 10.4) */
-#ifdef __APPLE__
-#include <TargetConditionals.h>
-#include <sys/resource.h>
-#ifdef HAVE_LIBPROC_H
-/* proc_name */
-#include <libproc.h>
-#endif
-#endif
-
-#if defined(PLATFORM_MACOSX)
-#define USE_OSX_LOADER
-#endif
-
-#if ( defined(__OpenBSD__) || defined(__FreeBSD__) ) && defined(HAVE_LINK_H)
-#define USE_BSD_LOADER
-#endif
-
-#if defined(__HAIKU__)
-#define USE_HAIKU_LOADER
-#endif
-
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER)
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-# if !defined(__OpenBSD__)
-# include <sys/utsname.h>
-# endif
-# if defined(__FreeBSD__)
-# include <sys/user.h> /* struct kinfo_proc */
-# endif
-#endif
-
-#ifdef PLATFORM_SOLARIS
-/* procfs.h cannot be included if this define is set, but it seems to work fine if it is undefined */
-#if _FILE_OFFSET_BITS == 64
-#undef _FILE_OFFSET_BITS
-#include <procfs.h>
-#define _FILE_OFFSET_BITS 64
-#else
-#include <procfs.h>
-#endif
-#endif
-
-#ifdef __HAIKU__
-#include <KernelKit.h>
-#endif
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/process-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/strenc.h>
-#include <mono/utils/mono-path.h>
-#include <mono/io-layer/timefuncs-private.h>
-#include <mono/utils/mono-time.h>
-#include <mono/utils/mono-membar.h>
-#include <mono/utils/mono-os-mutex.h>
-#include <mono/utils/mono-signal-handler.h>
-#include <mono/utils/mono-proclib.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
-
-#define STILL_ACTIVE STATUS_PENDING
-
-/* The process' environment strings */
-#if defined(__APPLE__)
-#if defined (TARGET_OSX)
-/* Apple defines this in crt_externs.h but doesn't provide that header for
- * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
- * in fact exist on all implementations (so far)
- */
-gchar ***_NSGetEnviron(void);
-#define environ (*_NSGetEnviron())
-#else
-static char *mono_environ[1] = { NULL };
-#define environ mono_environ
-#endif /* defined (TARGET_OSX) */
-#else
-extern char **environ;
-#endif
-
-static guint32 process_wait (gpointer handle, guint32 timeout, gboolean *alerted);
-static void process_close (gpointer handle, gpointer data);
-static void process_details (gpointer data);
-static const gchar* process_typename (void);
-static gsize process_typesize (void);
-static gboolean is_pid_valid (pid_t pid);
-
-#if !(defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER))
-static FILE *
-open_process_map (int pid, const char *mode);
-#endif
-
-static MonoW32HandleOps _wapi_process_ops = {
- process_close, /* close_shared */
- NULL, /* signal */
- NULL, /* own */
- NULL, /* is_owned */
- process_wait, /* special_wait */
- NULL, /* prewait */
- process_details, /* details */
- process_typename, /* typename */
- process_typesize, /* typesize */
-};
-
-#if HAVE_SIGACTION
-static struct sigaction previous_chld_sa;
-#endif
-static mono_once_t process_sig_chld_once = MONO_ONCE_INIT;
-static void process_add_sigchld_handler (void);
-
-/* The signal-safe logic to use mono_processes goes like this:
- * - The list must be safe to traverse for the signal handler at all times.
- * It's safe to: prepend an entry (which is a single store to 'mono_processes'),
- * unlink an entry (assuming the unlinked entry isn't freed and doesn't
- * change its 'next' pointer so that it can still be traversed).
- * When cleaning up we first unlink an entry, then we verify that
- * the read lock isn't locked. Then we can free the entry, since
- * we know that nobody is using the old version of the list (including
- * the unlinked entry).
- * We also need to lock when adding and cleaning up so that those two
- * operations don't mess with eachother. (This lock is not used in the
- * signal handler)
- */
-static struct MonoProcess *mono_processes = NULL;
-static volatile gint32 mono_processes_cleaning_up = 0;
-static mono_mutex_t mono_processes_mutex;
-static void mono_processes_cleanup (void);
-
-static gpointer current_process;
-static char *cli_launcher;
-
-static WapiHandle_process *
-lookup_process_handle (gpointer handle)
-{
- WapiHandle_process *process_data;
- gboolean ret;
-
- ret = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS,
- (gpointer *)&process_data);
- if (!ret)
- return NULL;
- return process_data;
-}
-
-/* Check if a pid is valid - i.e. if a process exists with this pid. */
-static gboolean
-is_pid_valid (pid_t pid)
-{
- gboolean result = FALSE;
-
-#if defined(HOST_WATCHOS)
- result = TRUE; // TODO: Rewrite using sysctl
-#elif defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__FreeBSD__)
- if (((kill(pid, 0) == 0) || (errno == EPERM)) && pid != 0)
- result = TRUE;
-#elif defined(__HAIKU__)
- team_info teamInfo;
- if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
- result = TRUE;
-#else
- char *dir = g_strdup_printf ("/proc/%d", pid);
- if (!access (dir, F_OK))
- result = TRUE;
- g_free (dir);
-#endif
-
- return result;
-}
-
-static void
-process_set_defaults (WapiHandle_process *process_handle)
-{
- /* These seem to be the defaults on w2k */
- process_handle->min_working_set = 204800;
- process_handle->max_working_set = 1413120;
-
- _wapi_time_t_to_filetime (time (NULL), &process_handle->create_time);
-}
-
-static int
-len16 (const gunichar2 *str)
-{
- int len = 0;
-
- while (*str++ != 0)
- len++;
-
- return len;
-}
-
-static gunichar2 *
-utf16_concat (const gunichar2 *first, ...)
-{
- va_list args;
- int total = 0, i;
- const gunichar2 *s;
- gunichar2 *ret;
-
- va_start (args, first);
- total += len16 (first);
- for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg(args, gunichar2 *)){
- total += len16 (s);
- }
- va_end (args);
-
- ret = g_new (gunichar2, total + 1);
- if (ret == NULL)
- return NULL;
-
- ret [total] = 0;
- i = 0;
- for (s = first; *s != 0; s++)
- ret [i++] = *s;
- va_start (args, first);
- for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg (args, gunichar2 *)){
- const gunichar2 *p;
-
- for (p = s; *p != 0; p++)
- ret [i++] = *p;
- }
- va_end (args);
-
- return ret;
-}
-
-static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 };
-static const gunichar2 *utf16_space = utf16_space_bytes;
-static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 };
-static const gunichar2 *utf16_quote = utf16_quote_bytes;
-
-#ifdef DEBUG_ENABLED
-/* Useful in gdb */
-void
-print_utf16 (gunichar2 *str)
-{
- char *res;
-
- res = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
- g_print ("%s\n", res);
- g_free (res);
-}
-#endif
-
-/* Implemented as just a wrapper around CreateProcess () */
-gboolean
-ShellExecuteEx (WapiShellExecuteInfo *sei)
-{
- gboolean ret;
- WapiProcessInformation process_info;
- gunichar2 *args;
-
- if (sei == NULL) {
- /* w2k just segfaults here, but we can do better than
- * that
- */
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- if (sei->lpFile == NULL)
- /* w2k returns TRUE for this, for some reason. */
- return TRUE;
-
- /* Put both executable and parameters into the second argument
- * to CreateProcess (), so it searches $PATH. The conversion
- * into and back out of utf8 is because there is no
- * g_strdup_printf () equivalent for gunichar2 :-(
- */
- args = utf16_concat (utf16_quote, sei->lpFile, utf16_quote, sei->lpParameters == NULL ? NULL : utf16_space, sei->lpParameters, NULL);
- if (args == NULL) {
- SetLastError (ERROR_INVALID_DATA);
- return FALSE;
- }
- ret = CreateProcess (NULL, args, NULL, NULL, TRUE,
- CREATE_UNICODE_ENVIRONMENT, NULL,
- sei->lpDirectory, NULL, &process_info);
- g_free (args);
-
- if (!ret && GetLastError () == ERROR_OUTOFMEMORY)
- return ret;
-
- if (!ret) {
- static char *handler;
- static gunichar2 *handler_utf16;
-
- if (handler_utf16 == (gunichar2 *)-1)
- return FALSE;
-
-#ifdef PLATFORM_MACOSX
- handler = g_strdup ("/usr/bin/open");
-#else
- /*
- * On Linux, try: xdg-open, the FreeDesktop standard way of doing it,
- * if that fails, try to use gnome-open, then kfmclient
- */
- handler = g_find_program_in_path ("xdg-open");
- if (handler == NULL){
- handler = g_find_program_in_path ("gnome-open");
- if (handler == NULL){
- handler = g_find_program_in_path ("kfmclient");
- if (handler == NULL){
- handler_utf16 = (gunichar2 *) -1;
- return FALSE;
- } else {
- /* kfmclient needs exec argument */
- char *old = handler;
- handler = g_strconcat (old, " exec",
- NULL);
- g_free (old);
- }
- }
- }
-#endif
- handler_utf16 = g_utf8_to_utf16 (handler, -1, NULL, NULL, NULL);
- g_free (handler);
-
- /* Put quotes around the filename, in case it's a url
- * that contains #'s (CreateProcess() calls
- * g_shell_parse_argv(), which deliberately throws
- * away anything after an unquoted #). Fixes bug
- * 371567.
- */
- args = utf16_concat (handler_utf16, utf16_space, utf16_quote,
- sei->lpFile, utf16_quote,
- sei->lpParameters == NULL ? NULL : utf16_space,
- sei->lpParameters, NULL);
- if (args == NULL) {
- SetLastError (ERROR_INVALID_DATA);
- return FALSE;
- }
- ret = CreateProcess (NULL, args, NULL, NULL, TRUE,
- CREATE_UNICODE_ENVIRONMENT, NULL,
- sei->lpDirectory, NULL, &process_info);
- g_free (args);
- if (!ret) {
- if (GetLastError () != ERROR_OUTOFMEMORY)
- SetLastError (ERROR_INVALID_DATA);
- return FALSE;
- }
- /* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */
- CloseHandle (process_info.hProcess);
- process_info.hProcess = NULL;
- }
-
- if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
- sei->hProcess = process_info.hProcess;
- else
- CloseHandle (process_info.hProcess);
-
- return ret;
-}
-
-static gboolean
-is_managed_binary (const char *filename)
-{
- int original_errno = errno;
-#if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE)
- int file = open (filename, O_RDONLY | O_LARGEFILE);
-#else
- int file = open (filename, O_RDONLY);
-#endif
- off_t new_offset;
- unsigned char buffer[8];
- off_t file_size, optional_header_offset;
- off_t pe_header_offset, clr_header_offset;
- gboolean managed = FALSE;
- int num_read;
- guint32 first_word, second_word, magic_number;
-
- /* If we are unable to open the file, then we definitely
- * can't say that it is managed. The child mono process
- * probably wouldn't be able to open it anyway.
- */
- if (file < 0) {
- errno = original_errno;
- return FALSE;
- }
-
- /* Retrieve the length of the file for future sanity checks. */
- file_size = lseek (file, 0, SEEK_END);
- lseek (file, 0, SEEK_SET);
-
- /* We know we need to read a header field at offset 60. */
- if (file_size < 64)
- goto leave;
-
- num_read = read (file, buffer, 2);
-
- if ((num_read != 2) || (buffer[0] != 'M') || (buffer[1] != 'Z'))
- goto leave;
-
- new_offset = lseek (file, 60, SEEK_SET);
-
- if (new_offset != 60)
- goto leave;
-
- num_read = read (file, buffer, 4);
-
- if (num_read != 4)
- goto leave;
- pe_header_offset = buffer[0]
- | (buffer[1] << 8)
- | (buffer[2] << 16)
- | (buffer[3] << 24);
-
- if (pe_header_offset + 24 > file_size)
- goto leave;
-
- new_offset = lseek (file, pe_header_offset, SEEK_SET);
-
- if (new_offset != pe_header_offset)
- goto leave;
-
- num_read = read (file, buffer, 4);
-
- if ((num_read != 4) || (buffer[0] != 'P') || (buffer[1] != 'E') || (buffer[2] != 0) || (buffer[3] != 0))
- goto leave;
-
- /*
- * Verify that the header we want in the optional header data
- * is present in this binary.
- */
- new_offset = lseek (file, pe_header_offset + 20, SEEK_SET);
-
- if (new_offset != pe_header_offset + 20)
- goto leave;
-
- num_read = read (file, buffer, 2);
-
- if ((num_read != 2) || ((buffer[0] | (buffer[1] << 8)) < 216))
- goto leave;
-
- optional_header_offset = pe_header_offset + 24;
-
- /* Read the PE magic number */
- new_offset = lseek (file, optional_header_offset, SEEK_SET);
-
- if (new_offset != optional_header_offset)
- goto leave;
-
- num_read = read (file, buffer, 2);
-
- if (num_read != 2)
- goto leave;
-
- magic_number = (buffer[0] | (buffer[1] << 8));
-
- if (magic_number == 0x10B) // PE32
- clr_header_offset = 208;
- else if (magic_number == 0x20B) // PE32+
- clr_header_offset = 224;
- else
- goto leave;
-
- /* Read the CLR header address and size fields. These will be
- * zero if the binary is not managed.
- */
- new_offset = lseek (file, optional_header_offset + clr_header_offset, SEEK_SET);
-
- if (new_offset != optional_header_offset + clr_header_offset)
- goto leave;
-
- num_read = read (file, buffer, 8);
-
- /* We are not concerned with endianness, only with
- * whether it is zero or not.
- */
- first_word = *(guint32 *)&buffer[0];
- second_word = *(guint32 *)&buffer[4];
-
- if ((num_read != 8) || (first_word == 0) || (second_word == 0))
- goto leave;
-
- managed = TRUE;
-
-leave:
- close (file);
- errno = original_errno;
- return managed;
-}
-
-gboolean
-CreateProcessWithLogonW (const gunichar2 *username,
- const gunichar2 *domain,
- const gunichar2 *password,
- const guint32 logonFlags,
- const gunichar2 *appname,
- const gunichar2 *cmdline,
- guint32 create_flags,
- gpointer env,
- const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info)
-{
- /* FIXME: use user information */
- return CreateProcess (appname, cmdline, NULL, NULL, FALSE, create_flags, env, cwd, startup, process_info);
-}
-
-static gboolean
-is_readable_or_executable (const char *prog)
-{
- struct stat buf;
- int a = access (prog, R_OK);
- int b = access (prog, X_OK);
- if (a != 0 && b != 0)
- return FALSE;
- if (stat (prog, &buf))
- return FALSE;
- if (S_ISREG (buf.st_mode))
- return TRUE;
- return FALSE;
-}
-
-static gboolean
-is_executable (const char *prog)
-{
- struct stat buf;
- if (access (prog, X_OK) != 0)
- return FALSE;
- if (stat (prog, &buf))
- return FALSE;
- if (S_ISREG (buf.st_mode))
- return TRUE;
- return FALSE;
-}
-
-static void
-switch_dir_separators (char *path)
-{
- size_t i, pathLength = strlen(path);
-
- /* Turn all the slashes round the right way, except for \' */
- /* There are probably other characters that need to be excluded as well. */
- for (i = 0; i < pathLength; i++) {
- if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' )
- path[i] = '/';
- }
-}
-
-gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
- WapiSecurityAttributes *process_attrs G_GNUC_UNUSED,
- WapiSecurityAttributes *thread_attrs G_GNUC_UNUSED,
- gboolean inherit_handles, guint32 create_flags,
- gpointer new_environ, const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info)
-{
-#if defined (HAVE_FORK) && defined (HAVE_EXECVE)
- char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL;
- char *dir = NULL, **env_strings = NULL, **argv = NULL;
- guint32 i, env_count = 0;
- gboolean ret = FALSE;
- gpointer handle = NULL;
- WapiHandle_process process_handle = {0}, *process_handle_data;
- GError *gerr = NULL;
- int in_fd, out_fd, err_fd;
- pid_t pid = 0;
- int startup_pipe [2] = {-1, -1};
- int dummy;
- struct MonoProcess *mono_process;
- gboolean fork_failed = FALSE;
-
- mono_once (&process_sig_chld_once, process_add_sigchld_handler);
-
- /* appname and cmdline specify the executable and its args:
- *
- * If appname is not NULL, it is the name of the executable.
- * Otherwise the executable is the first token in cmdline.
- *
- * Executable searching:
- *
- * If appname is not NULL, it can specify the full path and
- * file name, or else a partial name and the current directory
- * will be used. There is no additional searching.
- *
- * If appname is NULL, the first whitespace-delimited token in
- * cmdline is used. If the name does not contain a full
- * directory path, the search sequence is:
- *
- * 1) The directory containing the current process
- * 2) The current working directory
- * 3) The windows system directory (Ignored)
- * 4) The windows directory (Ignored)
- * 5) $PATH
- *
- * Just to make things more interesting, tokens can contain
- * white space if they are surrounded by quotation marks. I'm
- * beginning to understand just why windows apps are generally
- * so crap, with an API like this :-(
- */
- if (appname != NULL) {
- cmd = mono_unicode_to_external (appname);
- if (cmd == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL",
- __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
-
- switch_dir_separators(cmd);
- }
-
- if (cmdline != NULL) {
- args = mono_unicode_to_external (cmdline);
- if (args == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
- }
-
- if (cwd != NULL) {
- dir = mono_unicode_to_external (cwd);
- if (dir == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
-
- /* Turn all the slashes round the right way */
- switch_dir_separators(dir);
- }
-
-
- /* We can't put off locating the executable any longer :-( */
- if (cmd != NULL) {
- char *unquoted;
- if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) {
- /* Strip off the drive letter. I can't
- * believe that CP/M holdover is still
- * visible...
- */
- g_memmove (cmd, cmd+2, strlen (cmd)-2);
- cmd[strlen (cmd)-2] = '\0';
- }
-
- unquoted = g_shell_unquote (cmd, NULL);
- if (unquoted[0] == '/') {
- /* Assume full path given */
- prog = g_strdup (unquoted);
-
- /* Executable existing ? */
- if (!is_readable_or_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
- __func__, prog);
- g_free (unquoted);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- } else {
- /* Search for file named by cmd in the current
- * directory
- */
- char *curdir = g_get_current_dir ();
-
- prog = g_strdup_printf ("%s/%s", curdir, unquoted);
- g_free (curdir);
-
- /* And make sure it's readable */
- if (!is_readable_or_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
- __func__, prog);
- g_free (unquoted);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- }
- g_free (unquoted);
-
- args_after_prog = args;
- } else {
- char *token = NULL;
- char quote;
-
- /* Dig out the first token from args, taking quotation
- * marks into account
- */
-
- /* First, strip off all leading whitespace */
- args = g_strchug (args);
-
- /* args_after_prog points to the contents of args
- * after token has been set (otherwise argv[0] is
- * duplicated)
- */
- args_after_prog = args;
-
- /* Assume the opening quote will always be the first
- * character
- */
- if (args[0] == '\"' || args [0] == '\'') {
- quote = args [0];
- for (i = 1; args[i] != '\0' && args[i] != quote; i++);
- if (args [i + 1] == '\0' || g_ascii_isspace (args[i+1])) {
- /* We found the first token */
- token = g_strndup (args+1, i-1);
- args_after_prog = g_strchug (args + i + 1);
- } else {
- /* Quotation mark appeared in the
- * middle of the token. Just give the
- * whole first token, quotes and all,
- * to exec.
- */
- }
- }
-
- if (token == NULL) {
- /* No quote mark, or malformed */
- for (i = 0; args[i] != '\0'; i++) {
- if (g_ascii_isspace (args[i])) {
- token = g_strndup (args, i);
- args_after_prog = args + i + 1;
- break;
- }
- }
- }
-
- if (token == NULL && args[0] != '\0') {
- /* Must be just one token in the string */
- token = g_strdup (args);
- args_after_prog = NULL;
- }
-
- if (token == NULL) {
- /* Give up */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find what to exec", __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
-
- /* Turn all the slashes round the right way. Only for
- * the prg. name
- */
- switch_dir_separators(token);
-
- if (g_ascii_isalpha (token[0]) && (token[1] == ':')) {
- /* Strip off the drive letter. I can't
- * believe that CP/M holdover is still
- * visible...
- */
- g_memmove (token, token+2, strlen (token)-2);
- token[strlen (token)-2] = '\0';
- }
-
- if (token[0] == '/') {
- /* Assume full path given */
- prog = g_strdup (token);
-
- /* Executable existing ? */
- if (!is_readable_or_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
- __func__, token);
- g_free (token);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- } else {
- char *curdir = g_get_current_dir ();
-
- /* FIXME: Need to record the directory
- * containing the current process, and check
- * that for the new executable as the first
- * place to look
- */
-
- prog = g_strdup_printf ("%s/%s", curdir, token);
- g_free (curdir);
-
- /* I assume X_OK is the criterion to use,
- * rather than F_OK
- *
- * X_OK is too strict *if* the target is a CLR binary
- */
- if (!is_readable_or_executable (prog)) {
- g_free (prog);
- prog = g_find_program_in_path (token);
- if (prog == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s", __func__, token);
-
- g_free (token);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- }
- }
-
- g_free (token);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Exec prog [%s] args [%s]", __func__, prog,
- args_after_prog);
-
- /* Check for CLR binaries; if found, we will try to invoke
- * them using the same mono binary that started us.
- */
- if (is_managed_binary (prog)) {
- gunichar2 *newapp = NULL, *newcmd;
- gsize bytes_ignored;
-
- if (cli_launcher)
- newapp = mono_unicode_from_external (cli_launcher, &bytes_ignored);
- else
- newapp = mono_unicode_from_external ("mono", &bytes_ignored);
-
- if (newapp != NULL) {
- if (appname != NULL) {
- newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space,
- appname, utf16_space,
- cmdline, NULL);
- } else {
- newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space,
- cmdline, NULL);
- }
-
- g_free ((gunichar2 *)newapp);
-
- if (newcmd != NULL) {
- ret = CreateProcess (NULL, newcmd,
- process_attrs,
- thread_attrs,
- inherit_handles,
- create_flags, new_environ,
- cwd, startup,
- process_info);
-
- g_free ((gunichar2 *)newcmd);
-
- goto free_strings;
- }
- }
- } else {
- if (!is_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Executable permisson not set on %s", __func__, prog);
- SetLastError (ERROR_ACCESS_DENIED);
- goto free_strings;
- }
- }
-
- if (args_after_prog != NULL && *args_after_prog) {
- char *qprog;
-
- qprog = g_shell_quote (prog);
- full_prog = g_strconcat (qprog, " ", args_after_prog, NULL);
- g_free (qprog);
- } else {
- full_prog = g_shell_quote (prog);
- }
-
- ret = g_shell_parse_argv (full_prog, NULL, &argv, &gerr);
- if (ret == FALSE) {
- g_message ("CreateProcess: %s\n", gerr->message);
- g_error_free (gerr);
- gerr = NULL;
- goto free_strings;
- }
-
- if (startup != NULL && startup->dwFlags & STARTF_USESTDHANDLES) {
- in_fd = GPOINTER_TO_UINT (startup->hStdInput);
- out_fd = GPOINTER_TO_UINT (startup->hStdOutput);
- err_fd = GPOINTER_TO_UINT (startup->hStdError);
- } else {
- in_fd = GPOINTER_TO_UINT (GetStdHandle (STD_INPUT_HANDLE));
- out_fd = GPOINTER_TO_UINT (GetStdHandle (STD_OUTPUT_HANDLE));
- err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
- }
-
- process_handle.proc_name = g_strdup (prog);
-
- process_set_defaults (&process_handle);
-
- handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
- if (handle == INVALID_HANDLE_VALUE) {
- g_warning ("%s: error creating process handle", __func__);
-
- ret = FALSE;
- SetLastError (ERROR_OUTOFMEMORY);
- goto free_strings;
- }
-
- /* new_environ is a block of NULL-terminated strings, which
- * is itself NULL-terminated. Of course, passing an array of
- * string pointers would have made things too easy :-(
- *
- * If new_environ is not NULL it specifies the entire set of
- * environment variables in the new process. Otherwise the
- * new process inherits the same environment.
- */
- if (new_environ) {
- gunichar2 *new_environp;
-
- /* Count the number of strings */
- for (new_environp = (gunichar2 *)new_environ; *new_environp;
- new_environp++) {
- env_count++;
- while (*new_environp) {
- new_environp++;
- }
- }
-
- /* +2: one for the process handle value, and the last
- * one is NULL
- */
- env_strings = g_new0 (char *, env_count + 2);
-
- /* Copy each environ string into 'strings' turning it
- * into utf8 (or the requested encoding) at the same
- * time
- */
- env_count = 0;
- for (new_environp = (gunichar2 *)new_environ; *new_environp;
- new_environp++) {
- env_strings[env_count] = mono_unicode_to_external (new_environp);
- env_count++;
- while (*new_environp) {
- new_environp++;
- }
- }
- } else {
- for (i = 0; environ[i] != NULL; i++)
- env_count++;
-
- /* +2: one for the process handle value, and the last
- * one is NULL
- */
- env_strings = g_new0 (char *, env_count + 2);
-
- /* Copy each environ string into 'strings' turning it
- * into utf8 (or the requested encoding) at the same
- * time
- */
- env_count = 0;
- for (i = 0; environ[i] != NULL; i++) {
- env_strings[env_count] = g_strdup (environ[i]);
- env_count++;
- }
- }
-
- /* Create a pipe to make sure the child doesn't exit before
- * we can add the process to the linked list of mono_processes */
- if (pipe (startup_pipe) == -1) {
- /* Could not create the pipe to synchroniz process startup. We'll just not synchronize.
- * This is just for a very hard to hit race condition in the first place */
- startup_pipe [0] = startup_pipe [1] = -1;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__);
- }
-
- switch (pid = fork ()) {
- case -1: /* Error */ {
- SetLastError (ERROR_OUTOFMEMORY);
- ret = FALSE;
- fork_failed = TRUE;
- break;
- }
- case 0: /* Child */ {
- if (startup_pipe [0] != -1) {
- /* Wait until the parent has updated it's internal data */
- ssize_t _i G_GNUC_UNUSED = read (startup_pipe [0], &dummy, 1);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: child: parent has completed its setup", __func__);
- close (startup_pipe [0]);
- close (startup_pipe [1]);
- }
-
- /* should we detach from the process group? */
-
- /* Connect stdin, stdout and stderr */
- dup2 (in_fd, 0);
- dup2 (out_fd, 1);
- dup2 (err_fd, 2);
-
- if (inherit_handles != TRUE) {
- /* FIXME: do something here */
- }
-
- /* Close all file descriptors */
- for (i = mono_w32handle_fd_reserve - 1; i > 2; i--)
- close (i);
-
-#ifdef DEBUG_ENABLED
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: exec()ing [%s] in dir [%s]", __func__, cmd,
- dir == NULL?".":dir);
- for (i = 0; argv[i] != NULL; i++)
- g_message ("arg %d: [%s]", i, argv[i]);
-
- for (i = 0; env_strings[i] != NULL; i++)
- g_message ("env %d: [%s]", i, env_strings[i]);
-#endif
-
- /* set cwd */
- if (dir != NULL && chdir (dir) == -1) {
- /* set error */
- _exit (-1);
- }
-
- /* exec */
- execve (argv[0], argv, env_strings);
-
- /* set error */
- _exit (-1);
-
- break;
- }
- default: /* Parent */ {
- process_handle_data = lookup_process_handle (handle);
- if (!process_handle_data) {
- g_warning ("%s: error looking up process handle %p", __func__, handle);
- mono_w32handle_unref (handle);
- } else {
- process_handle_data->id = pid;
-
- /* Add our mono_process into the linked list of mono_processes */
- mono_process = (struct MonoProcess *) g_malloc0 (sizeof (struct MonoProcess));
- mono_process->pid = pid;
- mono_process->handle_count = 1;
- mono_os_sem_init (&mono_process->exit_sem, 0);
-
- /* 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;
-
- 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;
- process_info->dwProcessId = pid;
-
- /* FIXME: we might need to handle the thread info some day */
- process_info->hThread = INVALID_HANDLE_VALUE;
- process_info->dwThreadId = 0;
- }
- }
-
- break;
- }
- }
-
- if (fork_failed)
- mono_w32handle_unref (handle);
-
- if (startup_pipe [1] != -1) {
- /* Write 1 byte, doesn't matter what */
- ssize_t _i G_GNUC_UNUSED = write (startup_pipe [1], startup_pipe, 1);
- close (startup_pipe [0]);
- close (startup_pipe [1]);
- }
-
-free_strings:
- if (cmd)
- g_free (cmd);
- if (full_prog)
- g_free (full_prog);
- if (prog)
- g_free (prog);
- if (args)
- g_free (args);
- if (dir)
- g_free (dir);
- if (env_strings)
- g_strfreev (env_strings);
- if (argv)
- g_strfreev (argv);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p for pid %d", __func__, handle, pid);
-
- /* Check if something needs to be cleaned up. */
- mono_processes_cleanup ();
-
- return ret;
-#else
- SetLastError (ERROR_NOT_SUPPORTED);
- return FALSE;
-#endif // defined (HAVE_FORK) && defined (HAVE_EXECVE)
-}
-
-static void
-process_set_name (WapiHandle_process *process_handle)
-{
- char *progname, *utf8_progname, *slash;
-
- progname = g_get_prgname ();
- utf8_progname = mono_utf8_from_external (progname);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: using [%s] as prog name", __func__, progname);
-
- if (utf8_progname) {
- slash = strrchr (utf8_progname, '/');
- if (slash)
- process_handle->proc_name = g_strdup (slash+1);
- else
- process_handle->proc_name = g_strdup (utf8_progname);
- g_free (utf8_progname);
- }
-}
-
-void
-_wapi_processes_init (void)
-{
- pid_t pid = wapi_getpid ();
- WapiHandle_process process_handle = {0};
-
- mono_w32handle_register_ops (MONO_W32HANDLE_PROCESS, &_wapi_process_ops);
-
- mono_w32handle_register_capabilities (MONO_W32HANDLE_PROCESS,
- (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT));
-
- process_handle.id = pid;
-
- process_set_defaults (&process_handle);
- process_set_name (&process_handle);
-
- current_process = mono_w32handle_new (MONO_W32HANDLE_PROCESS,
- &process_handle);
- g_assert (current_process);
-
- mono_os_mutex_init (&mono_processes_mutex);
-}
-
-gpointer
-_wapi_process_duplicate (void)
-{
- mono_w32handle_ref (current_process);
-
- return current_process;
-}
-
-/* Returns a pseudo handle that doesn't need to be closed afterwards */
-gpointer
-GetCurrentProcess (void)
-{
- return _WAPI_PROCESS_CURRENT;
-}
-
-guint32
-GetProcessId (gpointer handle)
-{
- WapiHandle_process *process_handle;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
- /* This is a pseudo handle */
- return WAPI_HANDLE_TO_PID (handle);
-
- process_handle = lookup_process_handle (handle);
- if (!process_handle) {
- SetLastError (ERROR_INVALID_HANDLE);
- return 0;
- }
-
- return process_handle->id;
-}
-
-static gboolean
-process_open_compare (gpointer handle, gpointer user_data)
-{
- pid_t wanted_pid;
- WapiHandle_process *process_handle;
- pid_t checking_pid;
-
- g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
-
- process_handle = lookup_process_handle (handle);
- g_assert (process_handle);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking at process %d", __func__, process_handle->id);
-
- checking_pid = process_handle->id;
-
- if (checking_pid == 0)
- return FALSE;
-
- wanted_pid = GPOINTER_TO_UINT (user_data);
-
- /* It's possible to have more than one process handle with the
- * same pid, but only the one running process can be
- * unsignalled
- */
- if (checking_pid == wanted_pid &&
- !mono_w32handle_issignalled (handle)) {
- /* If the handle is blown away in the window between
- * returning TRUE here and mono_w32handle_search pinging
- * the timestamp, the search will continue
- */
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-gboolean
-CloseProcess (gpointer handle)
-{
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
- return TRUE;
- return CloseHandle (handle);
-}
-
-/*
- * The caller owns the returned handle and must call CloseProcess () on it to clean it up.
- */
-gpointer
-OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid)
-{
- /* Find the process handle that corresponds to pid */
- gpointer handle = NULL;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for process %d", __func__, pid);
-
- handle = mono_w32handle_search (MONO_W32HANDLE_PROCESS,
- process_open_compare,
- GUINT_TO_POINTER (pid), NULL, TRUE);
- if (handle == 0) {
- if (is_pid_valid (pid)) {
- /* Return a pseudo handle for processes we
- * don't have handles for
- */
- return WAPI_PID_TO_HANDLE (pid);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find pid %d", __func__, pid);
-
- SetLastError (ERROR_PROC_NOT_FOUND);
-
- return NULL;
- }
- }
-
- /* mono_w32handle_search () already added a ref */
- return handle;
-}
-
-gboolean
-GetExitCodeProcess (gpointer process, guint32 *code)
-{
- WapiHandle_process *process_handle;
- guint32 pid = -1;
- gboolean alerted;
-
- if (!code)
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = WAPI_HANDLE_TO_PID (process);
- /* This is a pseudo handle, so we don't know what the
- * exit code was, but we can check whether it's alive or not
- */
- if (is_pid_valid (pid)) {
- *code = STILL_ACTIVE;
- return TRUE;
- } else {
- *code = -1;
- return TRUE;
- }
- }
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- if (process_handle->id == wapi_getpid ()) {
- *code = STILL_ACTIVE;
- return TRUE;
- }
-
- /* A process handle is only signalled if the process has exited
- * and has been waited for */
-
- /* Make sure any process exit has been noticed, before
- * checking if the process is signalled. Fixes bug 325463.
- */
- process_wait (process, 0, &alerted);
-
- if (mono_w32handle_issignalled (process))
- *code = process_handle->exitstatus;
- else
- *code = STILL_ACTIVE;
-
- return TRUE;
-}
-
-gboolean
-GetProcessTimes (gpointer process, WapiFileTime *create_time,
- WapiFileTime *exit_time, WapiFileTime *kernel_time,
- WapiFileTime *user_time)
-{
- WapiHandle_process *process_handle;
- gboolean ku_times_set = FALSE;
-
- if (create_time == NULL || exit_time == NULL || kernel_time == NULL ||
- user_time == NULL)
- /* Not sure if w32 allows NULLs here or not */
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- gpointer pid = GINT_TO_POINTER (WAPI_HANDLE_TO_PID(process));
- gint64 start_ticks, user_ticks, kernel_ticks;
-
- mono_process_get_times (pid, &start_ticks, &user_ticks, &kernel_ticks);
-
- _wapi_guint64_to_filetime (start_ticks, create_time);
- _wapi_guint64_to_filetime (user_ticks, kernel_time);
- _wapi_guint64_to_filetime (kernel_ticks, user_time);
-
- return TRUE;
- }
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- *create_time = process_handle->create_time;
-
- /* A process handle is only signalled if the process has
- * exited. Otherwise exit_time isn't set
- */
- if (mono_w32handle_issignalled (process))
- *exit_time = process_handle->exit_time;
-
-#ifdef HAVE_GETRUSAGE
- if (process_handle->id == getpid ()) {
- struct rusage time_data;
- if (getrusage (RUSAGE_SELF, &time_data) == 0) {
- guint64 tick_val;
- ku_times_set = TRUE;
- tick_val = (guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10;
- _wapi_guint64_to_filetime (tick_val, user_time);
- tick_val = (guint64)time_data.ru_stime.tv_sec * 10000000 + (guint64)time_data.ru_stime.tv_usec * 10;
- _wapi_guint64_to_filetime (tick_val, kernel_time);
- }
- }
-#endif
- if (!ku_times_set) {
- memset (kernel_time, 0, sizeof (WapiFileTime));
- memset (user_time, 0, sizeof (WapiFileTime));
- }
-
- return TRUE;
-}
-
-typedef struct
-{
- gpointer address_start;
- gpointer address_end;
- char *perms;
- gpointer address_offset;
- guint64 device;
- guint64 inode;
- char *filename;
-} WapiProcModule;
-
-static void free_procmodule (WapiProcModule *mod)
-{
- if (mod->perms != NULL) {
- g_free (mod->perms);
- }
- if (mod->filename != NULL) {
- g_free (mod->filename);
- }
- g_free (mod);
-}
-
-static gint find_procmodule (gconstpointer a, gconstpointer b)
-{
- WapiProcModule *want = (WapiProcModule *)a;
- WapiProcModule *compare = (WapiProcModule *)b;
-
- if ((want->device == compare->device) &&
- (want->inode == compare->inode)) {
- return(0);
- } else {
- return(1);
- }
-}
-
-#if defined(USE_OSX_LOADER)
-#include <mach-o/dyld.h>
-#include <mach-o/getsect.h>
-
-static GSList *load_modules (void)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- uint32_t count = _dyld_image_count ();
- int i = 0;
-
- for (i = 0; i < count; i++) {
-#if SIZEOF_VOID_P == 8
- const struct mach_header_64 *hdr;
- const struct section_64 *sec;
-#else
- const struct mach_header *hdr;
- const struct section *sec;
-#endif
- const char *name;
-
- name = _dyld_get_image_name (i);
-#if SIZEOF_VOID_P == 8
- hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
- sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
-#else
- hdr = _dyld_get_image_header (i);
- sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
-#endif
-
- /* Some dynlibs do not have data sections on osx (#533893) */
- if (sec == 0) {
- continue;
- }
-
- mod = g_new0 (WapiProcModule, 1);
- mod->address_start = GINT_TO_POINTER (sec->addr);
- mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
- mod->perms = g_strdup ("r--p");
- mod->address_offset = 0;
- mod->device = makedev (0, 0);
- mod->inode = i;
- mod->filename = g_strdup (name);
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- ret = g_slist_reverse (ret);
-
- return(ret);
-}
-#elif defined(USE_BSD_LOADER)
-#include <link.h>
-static int load_modules_callback (struct dl_phdr_info *info, size_t size, void *ptr)
-{
- if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
- + sizeof (info->dlpi_phnum))
- return (-1);
-
- struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info));
- if (!cpy)
- return (-1);
-
- memcpy(cpy, info, sizeof(*info));
-
- g_ptr_array_add ((GPtrArray *)ptr, cpy);
-
- return (0);
-}
-
-static GSList *load_modules (void)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- GPtrArray *dlarray = g_ptr_array_new();
- int i;
-
- if (dl_iterate_phdr(load_modules_callback, dlarray) < 0)
- return (ret);
-
- for (i = 0; i < dlarray->len; i++) {
- struct dl_phdr_info *info = g_ptr_array_index (dlarray, i);
-
- mod = g_new0 (WapiProcModule, 1);
- mod->address_start = (gpointer)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
- mod->address_end = (gpointer)(info->dlpi_addr +
- info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr);
- mod->perms = g_strdup ("r--p");
- mod->address_offset = 0;
- mod->inode = i;
- mod->filename = g_strdup (info->dlpi_name);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p", __func__,
- mod->inode, mod->filename, mod->address_start, mod->address_end);
-
- g_free (info);
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- g_ptr_array_free (dlarray, TRUE);
-
- ret = g_slist_reverse (ret);
-
- return(ret);
-}
-#elif defined(USE_HAIKU_LOADER)
-
-static GSList *load_modules (void)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- int32 cookie = 0;
- image_info imageInfo;
-
- while (get_next_image_info (B_CURRENT_TEAM, &cookie, &imageInfo) == B_OK) {
- mod = g_new0 (WapiProcModule, 1);
- mod->device = imageInfo.device;
- mod->inode = imageInfo.node;
- mod->filename = g_strdup (imageInfo.name);
- mod->address_start = MIN (imageInfo.text, imageInfo.data);
- mod->address_end = MAX ((uint8_t*)imageInfo.text + imageInfo.text_size,
- (uint8_t*)imageInfo.data + imageInfo.data_size);
- mod->perms = g_strdup ("r--p");
- mod->address_offset = 0;
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- ret = g_slist_reverse (ret);
-
- return ret;
-}
-#else
-static GSList *load_modules (FILE *fp)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- char buf[MAXPATHLEN + 1], *p, *endp;
- char *start_start, *end_start, *prot_start, *offset_start;
- char *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
- gpointer address_start, address_end, address_offset;
- guint32 maj_dev, min_dev;
- guint64 inode;
- guint64 device;
-
- while (fgets (buf, sizeof(buf), fp)) {
- p = buf;
- while (g_ascii_isspace (*p)) ++p;
- start_start = p;
- if (!g_ascii_isxdigit (*start_start)) {
- continue;
- }
- address_start = (gpointer)strtoul (start_start, &endp, 16);
- p = endp;
- if (*p != '-') {
- continue;
- }
-
- ++p;
- end_start = p;
- if (!g_ascii_isxdigit (*end_start)) {
- continue;
- }
- address_end = (gpointer)strtoul (end_start, &endp, 16);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- while (g_ascii_isspace (*p)) ++p;
- prot_start = p;
- if (*prot_start != 'r' && *prot_start != '-') {
- continue;
- }
- memcpy (prot_buf, prot_start, 4);
- prot_buf[4] = '\0';
- while (!g_ascii_isspace (*p)) ++p;
-
- while (g_ascii_isspace (*p)) ++p;
- offset_start = p;
- if (!g_ascii_isxdigit (*offset_start)) {
- continue;
- }
- address_offset = (gpointer)strtoul (offset_start, &endp, 16);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- while(g_ascii_isspace (*p)) ++p;
- maj_dev_start = p;
- if (!g_ascii_isxdigit (*maj_dev_start)) {
- continue;
- }
- maj_dev = strtoul (maj_dev_start, &endp, 16);
- p = endp;
- if (*p != ':') {
- continue;
- }
-
- ++p;
- min_dev_start = p;
- if (!g_ascii_isxdigit (*min_dev_start)) {
- continue;
- }
- min_dev = strtoul (min_dev_start, &endp, 16);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- while (g_ascii_isspace (*p)) ++p;
- inode_start = p;
- if (!g_ascii_isxdigit (*inode_start)) {
- continue;
- }
- inode = (guint64)strtol (inode_start, &endp, 10);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- device = makedev ((int)maj_dev, (int)min_dev);
- if ((device == 0) &&
- (inode == 0)) {
- continue;
- }
-
- while(g_ascii_isspace (*p)) ++p;
- /* p now points to the filename */
-
- mod = g_new0 (WapiProcModule, 1);
- mod->address_start = address_start;
- mod->address_end = address_end;
- mod->perms = g_strdup (prot_buf);
- mod->address_offset = address_offset;
- mod->device = device;
- mod->inode = inode;
- mod->filename = g_strdup (g_strstrip (p));
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- ret = g_slist_reverse (ret);
-
- return(ret);
-}
-#endif
-
-static gboolean match_procname_to_modulename (char *procname, char *modulename)
-{
- char* lastsep = NULL;
- char* lastsep2 = NULL;
- char* pname = NULL;
- char* mname = NULL;
- gboolean result = FALSE;
-
- if (procname == NULL || modulename == NULL)
- return (FALSE);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: procname=\"%s\", modulename=\"%s\"", __func__, procname, modulename);
- pname = mono_path_resolve_symlinks (procname);
- mname = mono_path_resolve_symlinks (modulename);
-
- if (!strcmp (pname, mname))
- result = TRUE;
-
- if (!result) {
- lastsep = strrchr (mname, '/');
- if (lastsep)
- if (!strcmp (lastsep+1, pname))
- result = TRUE;
- if (!result) {
- lastsep2 = strrchr (pname, '/');
- if (lastsep2){
- if (lastsep) {
- if (!strcmp (lastsep+1, lastsep2+1))
- result = TRUE;
- } else {
- if (!strcmp (mname, lastsep2+1))
- result = TRUE;
- }
- }
- }
- }
-
- g_free (pname);
- g_free (mname);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: result is %d", __func__, result);
- return result;
-}
-
-#if !(defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER))
-static FILE *
-open_process_map (int pid, const char *mode)
-{
- FILE *fp = NULL;
- const char *proc_path[] = {
- "/proc/%d/maps", /* GNU/Linux */
- "/proc/%d/map", /* FreeBSD */
- NULL
- };
- int i;
- char *filename;
-
- for (i = 0; fp == NULL && proc_path [i]; i++) {
- filename = g_strdup_printf (proc_path[i], pid);
- fp = fopen (filename, mode);
- g_free (filename);
- }
-
- return fp;
-}
-#endif
-
-static char *get_process_name_from_proc (pid_t pid);
-
-gboolean EnumProcessModules (gpointer process, gpointer *modules,
- guint32 size, guint32 *needed)
-{
- WapiHandle_process *process_handle;
-#if !defined(USE_OSX_LOADER) && !defined(USE_BSD_LOADER)
- FILE *fp;
-#endif
- GSList *mods = NULL;
- WapiProcModule *module;
- guint32 count, avail = size / sizeof(gpointer);
- int i;
- pid_t pid;
- char *proc_name = NULL;
-
- /* Store modules in an array of pointers (main module as
- * modules[0]), using the load address for each module as a
- * token. (Use 'NULL' as an alternative for the main module
- * so that the simple implementation can just return one item
- * for now.) Get the info from /proc/<pid>/maps on linux,
- * /proc/<pid>/map on FreeBSD, other systems will have to
- * implement /dev/kmem reading or whatever other horrid
- * technique is needed.
- */
- if (size < sizeof(gpointer))
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = WAPI_HANDLE_TO_PID (process);
- proc_name = get_process_name_from_proc (pid);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
- }
-
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER)
- mods = load_modules ();
- if (!proc_name) {
- modules[0] = NULL;
- *needed = sizeof(gpointer);
- return TRUE;
- }
-#else
- fp = open_process_map (pid, "r");
- if (!fp) {
- /* No /proc/<pid>/maps so just return the main module
- * shortcut for now
- */
- modules[0] = NULL;
- *needed = sizeof(gpointer);
- g_free (proc_name);
- return TRUE;
- }
- mods = load_modules (fp);
- fclose (fp);
-#endif
- count = g_slist_length (mods);
-
- /* count + 1 to leave slot 0 for the main module */
- *needed = sizeof(gpointer) * (count + 1);
-
- /*
- * Use the NULL shortcut, as the first line in
- * /proc/<pid>/maps isn't the executable, and we need
- * that first in the returned list. Check the module name
- * to see if it ends with the proc name and substitute
- * the first entry with it. FIXME if this turns out to
- * be a problem.
- */
- modules[0] = NULL;
- for (i = 0; i < (avail - 1) && i < count; i++) {
- module = (WapiProcModule *)g_slist_nth_data (mods, i);
- if (modules[0] != NULL)
- modules[i] = module->address_start;
- else if (match_procname_to_modulename (proc_name, module->filename))
- modules[0] = module->address_start;
- else
- modules[i + 1] = module->address_start;
- }
-
- for (i = 0; i < count; i++) {
- free_procmodule ((WapiProcModule *)g_slist_nth_data (mods, i));
- }
- g_slist_free (mods);
- g_free (proc_name);
-
- return TRUE;
-}
-
-static char *
-get_process_name_from_proc (pid_t pid)
-{
-#if defined(USE_BSD_LOADER)
- int mib [6];
- size_t size;
- struct kinfo_proc *pi;
-#elif defined(USE_OSX_LOADER)
-#if !(!defined (__mono_ppc__) && defined (TARGET_OSX))
- size_t size;
- struct kinfo_proc *pi;
- int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
-#endif
-#else
- FILE *fp;
- char *filename = NULL;
-#endif
- char buf[256];
- char *ret = NULL;
-
-#if defined(PLATFORM_SOLARIS)
- filename = g_strdup_printf ("/proc/%d/psinfo", pid);
- if ((fp = fopen (filename, "r")) != NULL) {
- struct psinfo info;
- int nread;
-
- nread = fread (&info, sizeof (info), 1, fp);
- if (nread == 1) {
- ret = g_strdup (info.pr_fname);
- }
-
- fclose (fp);
- }
- g_free (filename);
-#elif defined(USE_OSX_LOADER)
-#if !defined (__mono_ppc__) && defined (TARGET_OSX)
- /* No proc name on OSX < 10.5 nor ppc nor iOS */
- memset (buf, '\0', sizeof(buf));
- proc_name (pid, buf, sizeof(buf));
-
- // Fixes proc_name triming values to 15 characters #32539
- if (strlen (buf) >= MAXCOMLEN - 1) {
- char path_buf [PROC_PIDPATHINFO_MAXSIZE];
- char *name_buf;
- int path_len;
-
- memset (path_buf, '\0', sizeof(path_buf));
- path_len = proc_pidpath (pid, path_buf, sizeof(path_buf));
-
- if (path_len > 0 && path_len < sizeof(path_buf)) {
- name_buf = path_buf + path_len;
- for(;name_buf > path_buf; name_buf--) {
- if (name_buf [0] == '/') {
- name_buf++;
- break;
- }
- }
-
- if (memcmp (buf, name_buf, MAXCOMLEN - 1) == 0)
- ret = g_strdup (name_buf);
- }
- }
-
- if (ret == NULL && strlen (buf) > 0)
- ret = g_strdup (buf);
-#else
- if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
- return(ret);
-
- if ((pi = g_malloc (size)) == NULL)
- return(ret);
-
- if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
- if (errno == ENOMEM) {
- g_free (pi);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
- }
- return(ret);
- }
-
- if (strlen (pi->kp_proc.p_comm) > 0)
- ret = g_strdup (pi->kp_proc.p_comm);
-
- g_free (pi);
-#endif
-#elif defined(USE_BSD_LOADER)
-#if defined(__FreeBSD__)
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC;
- mib [2] = KERN_PROC_PID;
- mib [3] = pid;
- if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
- return(ret);
- }
-
- if ((pi = g_malloc (size)) == NULL)
- return(ret);
-
- if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
- if (errno == ENOMEM) {
- g_free (pi);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
- }
- return(ret);
- }
-
- if (strlen (pi->ki_comm) > 0)
- ret = g_strdup (pi->ki_comm);
- g_free (pi);
-#elif defined(__OpenBSD__)
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC;
- mib [2] = KERN_PROC_PID;
- mib [3] = pid;
- mib [4] = sizeof(struct kinfo_proc);
- mib [5] = 0;
-
-retry:
- if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
- return(ret);
- }
-
- if ((pi = g_malloc (size)) == NULL)
- return(ret);
-
- mib[5] = (int)(size / sizeof(struct kinfo_proc));
-
- if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
- (size != sizeof (struct kinfo_proc))) {
- if (errno == ENOMEM) {
- g_free (pi);
- goto retry;
- }
- return(ret);
- }
-
- if (strlen (pi->p_comm) > 0)
- ret = g_strdup (pi->p_comm);
-
- g_free (pi);
-#endif
-#elif defined(USE_HAIKU_LOADER)
- image_info imageInfo;
- int32 cookie = 0;
-
- if (get_next_image_info ((team_id)pid, &cookie, &imageInfo) == B_OK) {
- ret = g_strdup (imageInfo.name);
- }
-#else
- memset (buf, '\0', sizeof(buf));
- filename = g_strdup_printf ("/proc/%d/exe", pid);
- if (readlink (filename, buf, 255) > 0) {
- ret = g_strdup (buf);
- }
- g_free (filename);
-
- if (ret != NULL) {
- return(ret);
- }
-
- filename = g_strdup_printf ("/proc/%d/cmdline", pid);
- if ((fp = fopen (filename, "r")) != NULL) {
- if (fgets (buf, 256, fp) != NULL) {
- ret = g_strdup (buf);
- }
-
- fclose (fp);
- }
- g_free (filename);
-
- if (ret != NULL) {
- return(ret);
- }
-
- filename = g_strdup_printf ("/proc/%d/stat", pid);
- if ((fp = fopen (filename, "r")) != NULL) {
- if (fgets (buf, 256, fp) != NULL) {
- char *start, *end;
-
- start = strchr (buf, '(');
- if (start != NULL) {
- end = strchr (start + 1, ')');
-
- if (end != NULL) {
- ret = g_strndup (start + 1,
- end - start - 1);
- }
- }
- }
-
- fclose (fp);
- }
- g_free (filename);
-#endif
-
- return ret;
-}
-
-/*
- * wapi_process_get_path:
- *
- * Return the full path of the executable of the process PID, or NULL if it cannot be determined.
- * Returns malloc-ed memory.
- */
-char*
-wapi_process_get_path (pid_t pid)
-{
-#if defined(PLATFORM_MACOSX) && !defined(__mono_ppc__) && defined(TARGET_OSX)
- char buf [PROC_PIDPATHINFO_MAXSIZE];
- int res;
-
- res = proc_pidpath (pid, buf, sizeof (buf));
- if (res <= 0)
- return NULL;
- if (buf [0] == '\0')
- return NULL;
- return g_strdup (buf);
-#else
- return get_process_name_from_proc (pid);
-#endif
-}
-
-/*
- * wapi_process_set_cli_launcher:
- *
- * Set the full path of the runtime executable used to launch managed exe's.
- */
-void
-wapi_process_set_cli_launcher (char *path)
-{
- g_free (cli_launcher);
- cli_launcher = path ? g_strdup (path) : NULL;
-}
-
-static guint32
-get_module_name (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size,
- gboolean base)
-{
- WapiHandle_process *process_handle;
- pid_t pid;
- gunichar2 *procname;
- char *procname_ext = NULL;
- glong len;
- gsize bytes;
-#if !defined(USE_OSX_LOADER) && !defined(USE_BSD_LOADER)
- FILE *fp;
-#endif
- GSList *mods = NULL;
- WapiProcModule *found_module;
- guint32 count;
- int i;
- char *proc_name = NULL;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module base name, process handle %p module %p",
- __func__, process, module);
-
- size = size * sizeof (gunichar2); /* adjust for unicode characters */
-
- if (basename == NULL || size == 0)
- return 0;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- proc_name = get_process_name_from_proc (pid);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__,
- process);
-
- return 0;
- }
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
- }
-
- /* Look up the address in /proc/<pid>/maps */
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER)
- mods = load_modules ();
-#else
- fp = open_process_map (pid, "r");
- if (fp == NULL) {
- if (errno == EACCES && module == NULL && base == TRUE) {
- procname_ext = get_process_name_from_proc (pid);
- } else {
- /* No /proc/<pid>/maps, so just return failure
- * for now
- */
- g_free (proc_name);
- return 0;
- }
- } else {
- mods = load_modules (fp);
- fclose (fp);
- }
-#endif
- count = g_slist_length (mods);
-
- /* If module != NULL compare the address.
- * If module == NULL we are looking for the main module.
- * The best we can do for now check it the module name end with the process name.
- */
- for (i = 0; i < count; i++) {
- found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
- if (procname_ext == NULL &&
- ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
- (module != NULL && found_module->address_start == module))) {
- if (base)
- procname_ext = g_path_get_basename (found_module->filename);
- else
- procname_ext = g_strdup (found_module->filename);
- }
-
- free_procmodule (found_module);
- }
-
- if (procname_ext == NULL) {
- /* If it's *still* null, we might have hit the
- * case where reading /proc/$pid/maps gives an
- * empty file for this user.
- */
- procname_ext = get_process_name_from_proc (pid);
- }
-
- g_slist_free (mods);
- g_free (proc_name);
-
- if (procname_ext) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Process name is [%s]", __func__,
- procname_ext);
-
- procname = mono_unicode_from_external (procname_ext, &bytes);
- if (procname == NULL) {
- /* bugger */
- g_free (procname_ext);
- return 0;
- }
-
- len = (bytes / 2);
-
- /* Add the terminator */
- bytes += 2;
-
- if (size < bytes) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
-
- memcpy (basename, procname, size);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
- __func__, size, bytes);
-
- memcpy (basename, procname, bytes);
- }
-
- g_free (procname);
- g_free (procname_ext);
-
- return len;
- }
-
- return 0;
-}
-
-static guint32
-get_module_filename (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size)
-{
- int pid, len;
- gsize bytes;
- char *path;
- gunichar2 *proc_path;
-
- size *= sizeof (gunichar2); /* adjust for unicode characters */
-
- if (basename == NULL || size == 0)
- return 0;
-
- pid = GetProcessId (process);
-
- path = wapi_process_get_path (pid);
- if (path == NULL)
- return 0;
-
- proc_path = mono_unicode_from_external (path, &bytes);
- g_free (path);
-
- if (proc_path == NULL)
- return 0;
-
- len = (bytes / 2);
-
- /* Add the terminator */
- bytes += 2;
-
- if (size < bytes) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
-
- memcpy (basename, proc_path, size);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
- __func__, size, bytes);
-
- memcpy (basename, proc_path, bytes);
- }
-
- g_free (proc_path);
-
- return len;
-}
-
-guint32
-GetModuleBaseName (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size)
-{
- return get_module_name (process, module, basename, size, TRUE);
-}
-
-guint32
-GetModuleFileNameEx (gpointer process, gpointer module,
- gunichar2 *filename, guint32 size)
-{
- return get_module_filename (process, module, filename, size);
-}
-
-gboolean
-GetModuleInformation (gpointer process, gpointer module,
- WapiModuleInfo *modinfo, guint32 size)
-{
- WapiHandle_process *process_handle;
- pid_t pid;
-#if !defined(USE_OSX_LOADER) && !defined(USE_BSD_LOADER)
- FILE *fp;
-#endif
- GSList *mods = NULL;
- WapiProcModule *found_module;
- guint32 count;
- int i;
- gboolean ret = FALSE;
- char *proc_name = NULL;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module info, process handle %p module %p",
- __func__, process, module);
-
- if (modinfo == NULL || size < sizeof (WapiModuleInfo))
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- proc_name = get_process_name_from_proc (pid);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__,
- process);
-
- return FALSE;
- }
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
- }
-
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER)
- mods = load_modules ();
-#else
- /* Look up the address in /proc/<pid>/maps */
- if ((fp = open_process_map (pid, "r")) == NULL) {
- /* No /proc/<pid>/maps, so just return failure
- * for now
- */
- g_free (proc_name);
- return FALSE;
- }
- mods = load_modules (fp);
- fclose (fp);
-#endif
- count = g_slist_length (mods);
-
- /* If module != NULL compare the address.
- * If module == NULL we are looking for the main module.
- * The best we can do for now check it the module name end with the process name.
- */
- for (i = 0; i < count; i++) {
- found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
- if (ret == FALSE &&
- ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
- (module != NULL && found_module->address_start == module))) {
- modinfo->lpBaseOfDll = found_module->address_start;
- modinfo->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start);
- modinfo->EntryPoint = found_module->address_offset;
- ret = TRUE;
- }
-
- free_procmodule (found_module);
- }
-
- g_slist_free (mods);
- g_free (proc_name);
-
- return ret;
-}
-
-gboolean
-GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
-{
- WapiHandle_process *process_handle;
-
- if (min == NULL || max == NULL)
- /* Not sure if w32 allows NULLs here or not */
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
- /* This is a pseudo handle, so just fail for now */
- return FALSE;
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- *min = process_handle->min_working_set;
- *max = process_handle->max_working_set;
-
- return TRUE;
-}
-
-gboolean
-SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
-{
- WapiHandle_process *process_handle;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
- /* This is a pseudo handle, so just fail for now
- */
- return FALSE;
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- process_handle->min_working_set = min;
- process_handle->max_working_set = max;
-
- return TRUE;
-}
-
-
-gboolean
-TerminateProcess (gpointer process, gint32 exitCode)
-{
-#if defined(HAVE_KILL)
- WapiHandle_process *process_handle;
- int signo;
- int ret;
- pid_t pid;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
- pid = process_handle->id;
- }
-
- signo = (exitCode == -1) ? SIGKILL : SIGTERM;
- ret = kill (pid, signo);
- if (ret == -1) {
- switch (errno) {
- case EINVAL:
- SetLastError (ERROR_INVALID_PARAMETER);
- break;
- case EPERM:
- SetLastError (ERROR_ACCESS_DENIED);
- break;
- case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
- break;
- default:
- SetLastError (ERROR_GEN_FAILURE);
- }
- }
-
- return (ret == 0);
-#else
- g_error ("kill() is not supported by this platform");
- return FALSE;
-#endif
-}
-
-guint32
-GetPriorityClass (gpointer process)
-{
-#ifdef HAVE_GETPRIORITY
- WapiHandle_process *process_handle;
- int ret;
- pid_t pid;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
- pid = process_handle->id;
- }
-
- errno = 0;
- ret = getpriority (PRIO_PROCESS, pid);
- if (ret == -1 && errno != 0) {
- switch (errno) {
- case EPERM:
- case EACCES:
- SetLastError (ERROR_ACCESS_DENIED);
- break;
- case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
- break;
- default:
- SetLastError (ERROR_GEN_FAILURE);
- }
- return FALSE;
- }
-
- if (ret == 0)
- return NORMAL_PRIORITY_CLASS;
- else if (ret < -15)
- return REALTIME_PRIORITY_CLASS;
- else if (ret < -10)
- return HIGH_PRIORITY_CLASS;
- else if (ret < 0)
- return ABOVE_NORMAL_PRIORITY_CLASS;
- else if (ret > 10)
- return IDLE_PRIORITY_CLASS;
- else if (ret > 0)
- return BELOW_NORMAL_PRIORITY_CLASS;
-
- return NORMAL_PRIORITY_CLASS;
-#else
- SetLastError (ERROR_NOT_SUPPORTED);
- return 0;
-#endif
-}
-
-gboolean
-SetPriorityClass (gpointer process, guint32 priority_class)
-{
-#ifdef HAVE_SETPRIORITY
- WapiHandle_process *process_handle;
- int ret;
- int prio;
- pid_t pid;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
- pid = process_handle->id;
- }
-
- switch (priority_class) {
- case IDLE_PRIORITY_CLASS:
- prio = 19;
- break;
- case BELOW_NORMAL_PRIORITY_CLASS:
- prio = 10;
- break;
- case NORMAL_PRIORITY_CLASS:
- prio = 0;
- break;
- case ABOVE_NORMAL_PRIORITY_CLASS:
- prio = -5;
- break;
- case HIGH_PRIORITY_CLASS:
- prio = -11;
- break;
- case REALTIME_PRIORITY_CLASS:
- prio = -20;
- break;
- default:
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- ret = setpriority (PRIO_PROCESS, pid, prio);
- if (ret == -1) {
- switch (errno) {
- case EPERM:
- case EACCES:
- SetLastError (ERROR_ACCESS_DENIED);
- break;
- case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
- break;
- default:
- SetLastError (ERROR_GEN_FAILURE);
- }
- }
-
- return ret == 0;
-#else
- SetLastError (ERROR_NOT_SUPPORTED);
- return FALSE;
-#endif
-}
-
-static void
-mono_processes_cleanup (void)
-{
- struct MonoProcess *mp;
- struct MonoProcess *prev = NULL;
- GSList *finished = NULL;
- GSList *l;
- gpointer unref_handle;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
-
- /* Ensure we're not in here in multiple threads at once, nor recursive. */
- if (InterlockedCompareExchange (&mono_processes_cleaning_up, 1, 0) != 0)
- return;
-
- for (mp = mono_processes; mp; mp = mp->next) {
- if (mp->pid == 0 && mp->handle) {
- /* This process has exited and we need to remove the artifical ref
- * on the handle */
- mono_os_mutex_lock (&mono_processes_mutex);
- unref_handle = mp->handle;
- mp->handle = NULL;
- mono_os_mutex_unlock (&mono_processes_mutex);
- if (unref_handle)
- mono_w32handle_unref (unref_handle);
- }
- }
-
- /*
- * Remove processes which exited from the mono_processes list.
- * We need to synchronize with the sigchld handler here, which runs
- * asynchronously. The handler requires that the mono_processes list
- * remain valid.
- */
- mono_os_mutex_lock (&mono_processes_mutex);
-
- mp = mono_processes;
- while (mp) {
- if (mp->handle_count == 0 && mp->freeable) {
- /*
- * Unlink the entry.
- * This code can run parallel with the sigchld handler, but the
- * modifications it makes are safe.
- */
- if (mp == mono_processes)
- mono_processes = mp->next;
- else
- prev->next = mp->next;
- finished = g_slist_prepend (finished, mp);
-
- mp = mp->next;
- } else {
- prev = mp;
- mp = mp->next;
- }
- }
-
- mono_memory_barrier ();
-
- for (l = finished; l; l = l->next) {
- /*
- * All the entries in the finished list are unlinked from mono_processes, and
- * they have the 'finished' flag set, which means the sigchld handler is done
- * accessing them.
- */
- mp = (MonoProcess *)l->data;
- mono_os_sem_destroy (&mp->exit_sem);
- g_free (mp);
- }
- g_slist_free (finished);
-
- mono_os_mutex_unlock (&mono_processes_mutex);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s done", __func__);
-
- InterlockedDecrement (&mono_processes_cleaning_up);
-}
-
-static void
-process_close (gpointer handle, gpointer data)
-{
- WapiHandle_process *process_handle;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
-
- process_handle = (WapiHandle_process *) data;
- g_free (process_handle->proc_name);
- process_handle->proc_name = NULL;
- if (process_handle->mono_process)
- InterlockedDecrement (&process_handle->mono_process->handle_count);
- mono_processes_cleanup ();
-}
-
-static void process_details (gpointer data)
-{
- WapiHandle_process *process_handle = (WapiHandle_process *) data;
- g_print ("id: %d, exited: %s, exitstatus: %d",
- process_handle->id, process_handle->exited ? "true" : "false", process_handle->exitstatus);
-}
-
-static const gchar* process_typename (void)
-{
- return "Process";
-}
-
-static gsize process_typesize (void)
-{
- return sizeof (WapiHandle_process);
-}
-
-#if HAVE_SIGACTION
-MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context))
-{
- int status;
- int pid;
- struct MonoProcess *p;
-
- do {
- do {
- pid = waitpid (-1, &status, WNOHANG);
- } while (pid == -1 && errno == EINTR);
-
- if (pid <= 0)
- break;
-
- /*
- * This can run concurrently with the code in the rest of this module.
- */
- for (p = mono_processes; p; p = p->next) {
- if (p->pid == pid) {
- break;
- }
- }
- if (p) {
- p->pid = 0; /* this pid doesn't exist anymore, clear it */
- p->status = status;
- mono_os_sem_post (&p->exit_sem);
- mono_memory_barrier ();
- /* Mark this as freeable, the pointer becomes invalid afterwards */
- p->freeable = TRUE;
- }
- } while (1);
-}
-
-#endif
-
-static void
-process_add_sigchld_handler (void)
-{
-#if HAVE_SIGACTION
- struct sigaction sa;
-
- sa.sa_sigaction = mono_sigchld_signal_handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
- g_assert (sigaction (SIGCHLD, &sa, &previous_chld_sa) != -1);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "Added SIGCHLD handler");
-#endif
-}
-
-static guint32
-process_wait (gpointer handle, guint32 timeout, gboolean *alerted)
-{
- WapiHandle_process *process_handle;
- pid_t pid G_GNUC_UNUSED, ret;
- int status;
- gint64 start, now;
- struct MonoProcess *mp;
-
- /* FIXME: We can now easily wait on processes that aren't our own children,
- * but WaitFor*Object won't call us for pseudo handles. */
- g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u)", __func__, handle, timeout);
-
- if (alerted)
- *alerted = FALSE;
-
- process_handle = lookup_process_handle (handle);
- if (!process_handle) {
- g_warning ("%s: error looking up process handle %p", __func__, handle);
- return WAIT_FAILED;
- }
-
- if (process_handle->exited) {
- /* We've already done this one */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Process already exited", __func__, handle, timeout);
- return WAIT_OBJECT_0;
- }
-
- pid = process_handle->id;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): PID: %d", __func__, handle, timeout, pid);
-
- /* We don't need to lock mono_processes here, the entry
- * has a handle_count > 0 which means it will not be freed. */
- mp = process_handle->mono_process;
- if (!mp) {
- pid_t res;
-
- if (pid == mono_process_current_pid ()) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on current process", __func__, handle, timeout);
- return WAIT_TIMEOUT;
- }
-
- /* This path is used when calling Process.HasExited, so
- * it is only used to poll the state of the process, not
- * to actually wait on it to exit */
- g_assert (timeout == 0);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on non-child process", __func__, handle, timeout);
-
- res = waitpid (pid, &status, WNOHANG);
- if (res == 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_TIMEOUT", __func__, handle, timeout);
- return WAIT_TIMEOUT;
- }
- if (res > 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process waited successfully", __func__, handle, timeout);
- return WAIT_OBJECT_0;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_FAILED, error : %s (%d))", __func__, handle, timeout, g_strerror (errno), errno);
- return WAIT_FAILED;
- }
-
- start = mono_msec_ticks ();
- now = start;
-
- while (1) {
- if (timeout != INFINITE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore for %li ms...",
- __func__, handle, timeout, (long)(timeout - (now - start)));
- ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore forever...",
- __func__, handle, timeout);
- ret = mono_os_sem_wait (&mp->exit_sem, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
- }
-
- if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
- /* Success, process has exited */
- mono_os_sem_post (&mp->exit_sem);
- break;
- }
-
- 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;
- }
-
- now = mono_msec_ticks ();
- if (now - start >= timeout) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
- return WAIT_TIMEOUT;
- }
-
- if (alerted && 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);
- *alerted = TRUE;
- return WAIT_IO_COMPLETION;
- }
- }
-
- /* Process must have exited */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Waited successfully", __func__, handle, timeout);
-
- status = mp ? mp->status : 0;
- if (WIFSIGNALED (status))
- process_handle->exitstatus = 128 + WTERMSIG (status);
- else
- process_handle->exitstatus = WEXITSTATUS (status);
- _wapi_time_t_to_filetime (time (NULL), &process_handle->exit_time);
-
- process_handle->exited = TRUE;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Setting pid %d signalled, exit status %d",
- __func__, handle, timeout, process_handle->id, process_handle->exitstatus);
-
- mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-
- return WAIT_OBJECT_0;
-}
-
-void
-wapi_processes_cleanup (void)
-{
- g_free (cli_launcher);
-}
+++ /dev/null
-/*
- * processes.h: Process handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_PROCESSES_H_
-#define _WAPI_PROCESSES_H_
-
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <glib.h>
-
-#include <mono/io-layer/access.h>
-#include <mono/io-layer/versioninfo.h>
-
-G_BEGIN_DECLS
-
-typedef enum {
- STARTF_USESHOWWINDOW=0x001,
- STARTF_USESIZE=0x002,
- STARTF_USEPOSITION=0x004,
- STARTF_USECOUNTCHARS=0x008,
- STARTF_USEFILLATTRIBUTE=0x010,
- STARTF_RUNFULLSCREEN=0x020,
- STARTF_FORCEONFEEDBACK=0x040,
- STARTF_FORCEOFFFEEDBACK=0x080,
- STARTF_USESTDHANDLES=0x100
-} WapiStartupFlags;
-
-
-typedef struct _WapiStartupInfo WapiStartupInfo;
-
-struct _WapiStartupInfo
-{
- guint32 cb;
- guchar *lpReserved;
- guchar *lpDesktop;
- guchar *lpTitle;
- guint32 dwX;
- guint32 dwY;
- guint32 dwXSize;
- guint32 dwYSize;
- guint32 dwXCountChars;
- guint32 dwYCountChars;
- guint32 dwFillAttribute;
- WapiStartupFlags dwFlags;
- guint16 wShowWindow;
- guint16 cbReserved2;
- guint8 *lpReserved2;
- gpointer hStdInput;
- gpointer hStdOutput;
- gpointer hStdError;
-};
-
-typedef struct _WapiProcessInformation WapiProcessInformation;
-
-struct _WapiProcessInformation
-{
- gpointer hProcess;
- gpointer hThread;
- guint32 dwProcessId;
- guint32 dwThreadId;
-};
-
-typedef enum {
- SEE_MASK_CLASSNAME = 0x01,
- SEE_MASK_CLASSKEY = 0x03,
- SEE_MASK_IDLIST = 0x04,
- SEE_MASK_INVOKEIDLIST = 0x0c,
- SEE_MASK_ICON = 0x10,
- SEE_MASK_HOTKEY = 0x20,
- SEE_MASK_NOCLOSEPROCESS = 0x40,
- SEE_MASK_CONNECTNETDRV = 0x80,
- SEE_MASK_FLAG_DDEWAIT = 0x100,
- SEE_MASK_DOENVSUBST = 0x200,
- SEE_MASK_FLAG_NO_UI = 0x400,
- SEE_MASK_NO_CONSOLE = 0x8000,
- SEE_MASK_UNICODE = 0x10000,
- SEE_MASK_HMONITOR = 0x200000,
- /*SEE_MASK_FLAG_LOG_USAGE,*/
- /*SEE_MASK_NOZONECHECKS,*/
-} WapiShellExecuteInfoFlags;
-
-typedef enum {
- SW_HIDE = 0,
- SW_SHOWNORMAL = 1,
- SW_SHOWMINIMIZED = 2,
- SW_MAXIMIZE = 3,
- SW_SHOWMAXIMIZED = 3,
- SW_SHOWNOACTIVATE = 4,
- SW_SHOW = 5,
- SW_MINIMIZE = 6,
- SW_SHOWMINNOACTIVE = 7,
- SW_SHOWNA = 8,
- SW_RESTORE = 9,
- SW_SHOWDEFAULT = 10,
-} WapiShellExecuteShowFlags;
-
-typedef struct _WapiShellExecuteInfo WapiShellExecuteInfo;
-
-struct _WapiShellExecuteInfo
-{
- guint32 cbSize;
- gulong fMask;
- gpointer hwnd;
- const gunichar2 *lpVerb;
- const gunichar2 *lpFile;
- const gunichar2 *lpParameters;
- const gunichar2 *lpDirectory;
- gulong nShow;
- gpointer hInstApp;
- gpointer lpIDList;
- const gunichar2 *lpClass;
- gpointer hkeyClass;
- guint32 dwHotKey;
- union
- {
- gpointer hIcon;
- gpointer hMonitor;
- } u;
- gpointer hProcess;
-};
-
-
-#define DEBUG_PROCESS 0x00000001
-#define DEBUG_ONLY_THIS_PROCESS 0x00000002
-#define DETACHED_PROCESS 0x00000008
-#define CREATE_NEW_CONSOLE 0x00000010
-#define NORMAL_PRIORITY_CLASS 0x00000020
-#define IDLE_PRIORITY_CLASS 0x00000040
-#define HIGH_PRIORITY_CLASS 0x00000080
-#define REALTIME_PRIORITY_CLASS 0x00000100
-#define CREATE_NEW_PROCESS_GROUP 0x00000200
-#define CREATE_UNICODE_ENVIRONMENT 0x00000400
-#define CREATE_SEPARATE_WOW_VDM 0x00000800
-#define CREATE_SHARED_WOW_VDM 0x00001000
-#define CREATE_FORCEDOS 0x00002000
-#define BELOW_NORMAL_PRIORITY_CLASS 0x00004000
-#define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
-#define CREATE_BREAKAWAY_FROM_JOB 0x01000000
-#define CREATE_WITH_USERPROFILE 0x02000000
-#define CREATE_DEFAULT_ERROR_MODE 0x04000000
-#define CREATE_NO_WINDOW 0x08000000
-
-#ifdef NEW_STUFF
-#define CREATE_PRESERVE_CODE_AUTHZ_LEVEL find out the value for this one...
-#endif
-
-#define PROCESS_TERMINATE 0x0001
-#define PROCESS_CREATE_THREAD 0x0002
-#define PROCESS_SET_SESSIONID 0x0004
-#define PROCESS_VM_OPERATION 0x0008
-#define PROCESS_VM_READ 0x0010
-#define PROCESS_VM_WRITE 0x0020
-#define PROCESS_DUP_HANDLE 0x0040
-#define PROCESS_CREATE_PROCESS 0x0080
-#define PROCESS_SET_QUOTA 0x0100
-#define PROCESS_SET_INFORMATION 0x0200
-#define PROCESS_QUERY_INFORMATION 0x0400
-#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xfff)
-
-extern gboolean ShellExecuteEx (WapiShellExecuteInfo *sei);
-extern gboolean CreateProcess (const gunichar2 *appname,
- const gunichar2 *cmdline,
- WapiSecurityAttributes *process_attrs,
- WapiSecurityAttributes *thread_attrs,
- gboolean inherit_handles, guint32 create_flags,
- gpointer environ, const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info);
-extern gboolean CreateProcessWithLogonW (const gunichar2 *username,
- const gunichar2 *domain,
- const gunichar2 *password,
- const guint32 logonFlags,
- const gunichar2 *appname,
- const gunichar2 *cmdline,
- guint32 create_flags,
- gpointer environ,
- const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info);
-#define LOGON_WITH_PROFILE 0x00000001
-#define LOGON_NETCREDENTIALS_ONLY 0x00000002
-
-extern gpointer GetCurrentProcess (void);
-extern guint32 GetProcessId (gpointer handle);
-extern gboolean CloseProcess (gpointer handle);
-extern gpointer OpenProcess (guint32 access, gboolean inherit, guint32 pid);
-extern gboolean GetExitCodeProcess (gpointer process, guint32 *code);
-extern gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
- WapiFileTime *exit_time,
- WapiFileTime *kernel_time,
- WapiFileTime *user_time);
-extern gboolean EnumProcessModules (gpointer process, gpointer *modules,
- guint32 size, guint32 *needed);
-extern guint32 GetModuleBaseName (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size);
-extern guint32 GetModuleFileNameEx (gpointer process, gpointer module,
- gunichar2 *filename, guint32 size);
-extern gboolean GetModuleInformation (gpointer process, gpointer module,
- WapiModuleInfo *modinfo, guint32 size);
-extern gboolean GetProcessWorkingSetSize (gpointer process, size_t *min,
- size_t *max);
-extern gboolean SetProcessWorkingSetSize (gpointer process, size_t min,
- size_t max);
-
-extern gboolean TerminateProcess (gpointer process, gint32 exitCode);
-
-extern guint32 GetPriorityClass (gpointer process);
-extern gboolean SetPriorityClass (gpointer process, guint32 priority_class);
-
-gchar* wapi_process_get_path (pid_t pid);
-
-void wapi_process_set_cli_launcher (char *path);
-
-G_END_DECLS
-
-#endif /* _WAPI_PROCESSES_H_ */
#include <mono/utils/mono-poll.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
+++ /dev/null
-/*
- * timefuncs-private.h: performance timer and other time private functions
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_TIMEFUNCS_PRIVATE_H_
-#define _WAPI_TIMEFUNCS_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <sys/time.h>
-
-extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
-extern void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime);
-
-#endif /* _WAPI_TIMEFUNCS_PRIVATE_H_ */
#include <stdio.h>
#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/timefuncs-private.h>
+#include <mono/io-layer/timefuncs.h>
#include "mono/utils/mono-time.h"
#undef DEBUG
filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
filetime->dwHighDateTime = ticks >> 32;
}
-
-void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime)
-{
- filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
- filetime->dwHighDateTime = ticks >> 32;
-}
#include <glib.h>
+#include <sys/time.h>
+
#include "mono/io-layer/wapi.h"
G_BEGIN_DECLS
#endif
} WapiFileTime;
+extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
+
G_END_DECLS
#endif /* _WAPI_TIME_H_ */
typedef WapiFindData *LPWIN32_FIND_DATA;
typedef WapiFileAttributesData WIN32_FILE_ATTRIBUTE_DATA;
typedef WapiGetFileExInfoLevels GET_FILEEX_INFO_LEVELS;
-typedef WapiStartupInfo STARTUPINFO;
-typedef WapiStartupInfo *LPSTARTUPINFO;
-typedef WapiProcessInformation PROCESS_INFORMATION;
typedef WapiFixedFileInfo VS_FIXEDFILEINFO;
typedef WapiModuleInfo MODULEINFO;
typedef WapiModuleInfo *LPMODULEINFO;
typedef WapiImageResourceDirectoryEntry *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
typedef WapiImageResourceDataEntry IMAGE_RESOURCE_DATA_ENTRY;
typedef WapiImageResourceDataEntry *PIMAGE_RESOURCE_DATA_ENTRY;
-typedef WapiShellExecuteInfo SHELLEXECUTEINFO;
-typedef WapiShellExecuteInfo *LPSHELLEXECUTEINFO;
typedef WapiTransmitFileBuffers TRANSMIT_FILE_BUFFERS;
typedef WapiTransmitFileBuffers *PTRANSMIT_FILE_BUFFERS;
typedef WapiTransmitFileBuffers *LPTRANSMIT_FILE_BUFFERS;
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
/**
* WaitForSingleObjectEx:
#define _WAPI_WAIT_H_
#include "mono/io-layer/status.h"
-#include "mono/utils/w32handle.h"
+#include "mono/metadata/w32handle.h"
G_BEGIN_DECLS
#include <mono/io-layer/io-private.h>
#include <mono/io-layer/socket-private.h>
-#include <mono/io-layer/process-private.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
struct _WapiHandle_shared_ref
{
#define UnlockFile wapi_UnlockFile
#define GetVolumeInformation wapi_GetVolumeInformation
#define FormatMessage wapi_FormatMessage
-#define ShellExecuteEx wapi_ShellExecuteEx
-#define CreateProcess wapi_CreateProcess
-#define CreateProcessWithLogonW wapi_CreateProcessWithLogonW
-#define GetCurrentProcess wapi_GetCurrentProcess
-#define GetProcessId wapi_GetProcessId
-#define CloseProcess wapi_CloseProcess
-#define OpenProcess wapi_OpenProcess
-#define GetExitCodeProcess wapi_GetExitCodeProcess
-#define GetProcessTimes wapi_GetProcessTimes
-#define EnumProcessModules wapi_EnumProcessModules
-#define GetModuleBaseName wapi_GetModuleBaseName
-#define GetModuleFileNameEx wapi_GetModuleFileNameEx
-#define GetModuleInformation wapi_GetModuleInformation
-#define GetProcessWorkingSetSize wapi_GetProcessWorkingSetSize
-#define SetProcessWorkingSetSize wapi_SetProcessWorkingSetSize
-#define TerminateProcess wapi_TerminateProcess
-#define GetPriorityClass wapi_GetPriorityClass
-#define SetPriorityClass wapi_SetPriorityClass
#define ImpersonateLoggedOnUser wapi_ImpersonateLoggedOnUser
#define RevertToSelf wapi_RevertToSelf
#define WSASetLastError wapi_WSASetLastError
#include "io-trace.h"
#include "io.h"
-#include "process-private.h"
#include "socket-private.h"
#include "mono/utils/mono-lazy-init.h"
-#include "mono/utils/w32handle.h"
+#include "mono/metadata/w32handle.h"
gboolean _wapi_has_shut_down = FALSE;
wapi_init (void)
{
_wapi_io_init ();
- _wapi_processes_init ();
_wapi_socket_init ();
}
_wapi_has_shut_down = TRUE;
_wapi_error_cleanup ();
- wapi_processes_cleanup ();
_wapi_io_cleanup ();
}
DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED)
{
- if (srcprocess != _WAPI_PROCESS_CURRENT || targetprocess != _WAPI_PROCESS_CURRENT) {
- /* Duplicating other process's handles is not supported */
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- if (src == _WAPI_PROCESS_CURRENT) {
- *target = _wapi_process_duplicate ();
- } else {
- mono_w32handle_ref (src);
- *target = src;
- }
-
+ mono_w32handle_ref (src);
+ *target = src;
return TRUE;
}
#include <mono/io-layer/types.h>
#include <mono/io-layer/macros.h>
#include <mono/io-layer/io.h>
-#include <mono/io-layer/access.h>
#include <mono/io-layer/context.h>
#include <mono/io-layer/error.h>
#include <mono/io-layer/messages.h>
-#include <mono/io-layer/processes.h>
#include <mono/io-layer/security.h>
#include <mono/io-layer/sockets.h>
#include <mono/io-layer/status.h>
marshal-windows-internals.h \
mono-security-windows.c \
mono-security-windows-internals.h \
- process-windows.c \
- process-windows-internals.h \
w32mutex-win32.c \
w32semaphore-win32.c \
w32event-win32.c \
+ w32process-win32.c \
+ w32process-win32-internals.h \
socket-io-windows.c
platform_sources = $(win32_sources)
console-unix.c \
w32mutex-unix.c \
w32semaphore-unix.c \
- w32event-unix.c
+ w32event-unix.c \
+ w32process-unix.c \
+ w32process-unix-internals.h \
+ w32process-unix-osx.c \
+ w32process-unix-bsd.c \
+ w32process-unix-haiku.c \
+ w32process-unix-default.c
platform_sources = $(unix_sources)
endif
cil-coff.h \
class.c \
class-internals.h \
+ class-inlines.h \
+ class-accessors.c \
cominterop.c \
cominterop.h \
console-io.h \
opcodes.c \
socket-io.c \
socket-io.h \
- process.c \
- process.h \
- process-internals.h \
+ w32process.c \
+ w32process.h \
+ w32process-internals.h \
profiler.c \
profiler-private.h \
rand.h \
w32semaphore.h \
w32event.h \
w32handle-namespace.h \
- w32handle-namespace.c
+ w32handle-namespace.c \
+ w32handle.h \
+ w32handle.c
# These source files have compile time dependencies on GC code
gc_dependent_sources = \
#include <mono/utils/atomic.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-threads.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
#ifdef HOST_WIN32
#include <direct.h>
#endif
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
-#define MONO_CORLIB_VERSION 160
+#define MONO_CORLIB_VERSION 162
typedef struct
{
mono_domain_try_unload (domain, &exc);
}
-static guint32
-guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
+static MonoThreadInfoWaitRet
+guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable)
{
- guint32 result;
+ MonoThreadInfoWaitRet result;
MONO_ENTER_GC_SAFE;
- result = WaitForSingleObjectEx (handle, timeout, alertable);
+ result = mono_thread_info_wait_one_handle (thread_handle, timeout, alertable);
MONO_EXIT_GC_SAFE;
return result;
mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
{
MonoError error;
- HANDLE thread_handle;
+ MonoThreadHandle *thread_handle;
MonoAppDomainState prev_state;
MonoMethod *method;
unload_data *thread_data;
return;
/* Wait for the thread */
- while (!thread_data->done && guarded_wait (thread_handle, INFINITE, TRUE) == WAIT_IO_COMPLETION) {
+ while (!thread_data->done && guarded_wait (thread_handle, INFINITE, TRUE) == MONO_THREAD_INFO_WAIT_RET_ALERTED) {
if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain) && (mono_thread_interruption_requested ())) {
/* The unload thread tries to abort us */
/* The icall wrapper will execute the abort */
#include "object-internals.h"
#include <mono/metadata/loader.h>
#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/custom-attrs-internals.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/class-internals.h>
/* Class lazy loading functions */
static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, InternalsVisibleToAttribute)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (reference_assembly, System.Runtime.CompilerServices, ReferenceAssemblyAttribute)
-
static MonoAssembly*
mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload);
static MonoAssembly*
if (ass->friend_assembly_names_inited)
return;
- attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
+ attrs = mono_custom_attrs_from_assembly_checked (ass, FALSE, &error);
mono_error_assert_ok (&error);
if (!attrs) {
mono_assemblies_lock ();
mono_assemblies_unlock ();
}
+struct HasReferenceAssemblyAttributeIterData {
+ gboolean has_attr;
+};
+
+static gboolean
+has_reference_assembly_attribute_iterator (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, gpointer user_data)
+{
+ gboolean stop_scanning = FALSE;
+ struct HasReferenceAssemblyAttributeIterData *iter_data = (struct HasReferenceAssemblyAttributeIterData*)user_data;
+
+ if (!strcmp (name, "ReferenceAssemblyAttribute") && !strcmp (nspace, "System.Runtime.CompilerServices")) {
+ /* Note we don't check the assembly name, same as coreCLR. */
+ iter_data->has_attr = TRUE;
+ stop_scanning = TRUE;
+ }
+
+ return stop_scanning;
+}
/**
* mono_assembly_has_reference_assembly_attribute:
{
mono_error_init (error);
-/* TODO: mono_custom_attrs_from_assembly_checked returns NULL if a
- * single assembly is missing. The custom attr we want is from
- * corlib, however, so we need a more robust version that doesn't care
- * about missing attributes.
- */
-#if 0
- MonoCustomAttrInfo *attrs = mono_custom_attrs_from_assembly_checked (assembly, error);
- return_val_if_nok (error, FALSE);
- if (!attrs)
- return FALSE;
- MonoClass *ref_asm_class = mono_class_try_get_reference_assembly_class ();
- g_assert (ref_asm_class != NULL && ref_asm_class != mono_defaults.object_class && !strcmp(ref_asm_class->name, "ReferenceAssemblyAttribute") );
- gboolean result = mono_custom_attrs_has_attr (attrs, ref_asm_class);
- mono_custom_attrs_free (attrs);
- return result;
-#else
- return FALSE;
-#endif
+ /*
+ * This might be called during assembly loading, so do everything using the low-level
+ * metadata APIs.
+ */
+
+ struct HasReferenceAssemblyAttributeIterData iter_data = { FALSE };
+
+ mono_assembly_metadata_foreach_custom_attr (assembly, &has_reference_assembly_attribute_iterator, &iter_data);
+
+ return iter_data.has_attr;
}
/**
}
}
- mono_assemblies_lock ();
-
- if (image->assembly) {
- /*
- * This means another thread has already loaded the assembly, but not yet
- * called the load hooks so the search hook can't find the assembly.
- */
- mono_assemblies_unlock ();
- ass2 = image->assembly;
- g_free (ass);
- g_free (base_dir);
- mono_image_close (image);
- *status = MONO_IMAGE_OK;
- return ass2;
- }
-
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
-
/* We need to check for ReferenceAssmeblyAttribute before we
* mark the assembly as loaded and before we fire the load
* hook. Otherwise mono_domain_fire_assembly_load () in
* this image and we won't be able to look for a different
* candidate. */
- if (!refonly && strcmp (ass->aname.name, "mscorlib") != 0) {
- /* Don't check for reference assmebly attribute for
- * corlib here because if corlib isn't loaded yet,
- * it's too early to set up the
- * ReferenceAssemblyAttribute class. We check that
- * we're not running with a reference corlib in
- * mono_init_internal().
- */
+ if (!refonly) {
MonoError refasm_error;
if (mono_assembly_has_reference_assembly_attribute (ass, &refasm_error)) {
- mono_assemblies_unlock ();
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image for assembly '%s' (%s) has ReferenceAssemblyAttribute, skipping", ass->aname.name, image->name);
g_free (ass);
g_free (base_dir);
mono_error_cleanup (&refasm_error);
}
+ mono_assemblies_lock ();
+
+ if (image->assembly) {
+ /*
+ * This means another thread has already loaded the assembly, but not yet
+ * called the load hooks so the search hook can't find the assembly.
+ */
+ mono_assemblies_unlock ();
+ ass2 = image->assembly;
+ g_free (ass);
+ g_free (base_dir);
+ mono_image_close (image);
+ *status = MONO_IMAGE_OK;
+ return ass2;
+ }
+
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
+
image->assembly = ass;
loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
static char *server_uri;
-static HANDLE receiver_thread_handle;
+static MonoThreadHandle *receiver_thread_handle;
static gboolean stop_receiver_thread;
/* Wait for the receiver thread to exit */
if (receiver_thread_handle)
- WaitForSingleObjectEx (receiver_thread_handle, 0, FALSE);
+ mono_thread_info_wait_one_handle (receiver_thread_handle, 0, FALSE);
}
static int
static MonoMethod* alloc_method_cache [ATYPE_NUM];
static MonoMethod* slowpath_alloc_method_cache [ATYPE_NUM];
-static G_GNUC_UNUSED gboolean
+gboolean
mono_gc_is_critical_method (MonoMethod *method)
{
int i;
#else
-static G_GNUC_UNUSED gboolean
+gboolean
mono_gc_is_critical_method (MonoMethod *method)
{
return FALSE;
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/tabledefs.h>
+
+
+/* Accessors based on class kind*/
+
+/*
+* mono_class_get_generic_class:
+*
+* Return the MonoGenericClass of @klass, which MUST be a generic instance.
+*/
+MonoGenericClass*
+mono_class_get_generic_class (MonoClass *klass)
+{
+ g_assert (mono_class_is_ginst (klass));
+ return ((MonoClassGenericInst*)klass)->generic_class;
+}
+
+/*
+* mono_class_try_get_generic_class:
+*
+* Return the MonoGenericClass if @klass is a ginst, NULL otherwise
+*/
+MonoGenericClass*
+mono_class_try_get_generic_class (MonoClass *klass)
+{
+ if (mono_class_is_ginst (klass))
+ return ((MonoClassGenericInst*)klass)->generic_class;
+ return NULL;
+}
+
+/**
+ * mono_class_get_flags:
+ * @klass: the MonoClass to act on
+ *
+ * Return the TypeAttributes flags of @klass.
+ * See the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the different values.
+ *
+ * Returns: The type flags
+ */
+guint32
+mono_class_get_flags (MonoClass *klass)
+{
+ switch (klass->class_kind) {
+ case MONO_CLASS_DEF:
+ case MONO_CLASS_GTD:
+ return ((MonoClassDef*)klass)->flags;
+ case MONO_CLASS_GINST:
+ return mono_class_get_flags (((MonoClassGenericInst*)klass)->generic_class->container_class);
+ case MONO_CLASS_GPARAM:
+ return TYPE_ATTRIBUTE_PUBLIC;
+ case MONO_CLASS_ARRAY:
+ /* all arrays are marked serializable and sealed, bug #42779 */
+ return TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
+ case MONO_CLASS_POINTER:
+ return TYPE_ATTRIBUTE_CLASS | (mono_class_get_flags (klass->element_class) & TYPE_ATTRIBUTE_VISIBILITY_MASK);
+ }
+ g_assert_not_reached ();
+}
+
+void
+mono_class_set_flags (MonoClass *klass, guint32 flags)
+{
+ g_assert (klass->class_kind == MONO_CLASS_DEF || klass->class_kind == MONO_CLASS_GTD);
+ ((MonoClassDef*)klass)->flags = flags;
+}
+
+/*
+ * mono_class_get_generic_container:
+ *
+ * Return the generic container of KLASS which should be a generic type definition.
+ */
+MonoGenericContainer*
+mono_class_get_generic_container (MonoClass *klass)
+{
+ g_assert (mono_class_is_gtd (klass));
+
+ return ((MonoClassGtd*)klass)->generic_container;
+}
+
+MonoGenericContainer*
+mono_class_try_get_generic_container (MonoClass *klass)
+{
+ if (mono_class_is_gtd (klass))
+ return ((MonoClassGtd*)klass)->generic_container;
+ return NULL;
+}
+
+
+void
+mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container)
+{
+ g_assert (mono_class_is_gtd (klass));
+
+ ((MonoClassGtd*)klass)->generic_container = container;
+}
+
+/*
+ * mono_class_get_first_method_idx:
+ *
+ * Return the table index of the first method for metadata classes.
+ */
+guint32
+mono_class_get_first_method_idx (MonoClass *klass)
+{
+ g_assert (mono_class_has_static_metadata (klass));
+
+ return ((MonoClassDef*)klass)->first_method_idx;
+}
+
+void
+mono_class_set_first_method_idx (MonoClass *klass, guint32 idx)
+{
+ g_assert (mono_class_has_static_metadata (klass));
+
+ ((MonoClassDef*)klass)->first_method_idx = idx;
+}
+
+guint32
+mono_class_get_first_field_idx (MonoClass *klass)
+{
+ if (mono_class_is_ginst (klass))
+ return mono_class_get_first_field_idx (mono_class_get_generic_class (klass)->container_class);
+
+ g_assert (mono_class_has_static_metadata (klass));
+
+ return ((MonoClassDef*)klass)->first_field_idx;
+}
+
+void
+mono_class_set_first_field_idx (MonoClass *klass, guint32 idx)
+{
+ g_assert (mono_class_has_static_metadata (klass));
+
+ ((MonoClassDef*)klass)->first_field_idx = idx;
+}
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_CLASS_INLINES_H__
+#define __MONO_METADATA_CLASS_INLINES_H__
+
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/tabledefs.h>
+
+static inline gboolean
+mono_class_is_def (MonoClass *klass)
+{
+ return klass->class_kind == MONO_CLASS_DEF;
+}
+
+static inline gboolean
+mono_class_is_gtd (MonoClass *klass)
+{
+ return klass->class_kind == MONO_CLASS_GTD;
+}
+
+static inline gboolean
+mono_class_is_ginst (MonoClass *klass)
+{
+ return klass->class_kind == MONO_CLASS_GINST;
+}
+
+static inline gboolean
+mono_class_is_gparam (MonoClass *klass)
+{
+ return klass->class_kind == MONO_CLASS_GPARAM;
+}
+
+static inline gboolean
+mono_class_is_array (MonoClass *klass)
+{
+ return klass->class_kind == MONO_CLASS_ARRAY;
+}
+
+static inline gboolean
+mono_class_is_pointer (MonoClass *klass)
+{
+ return klass->class_kind == MONO_CLASS_POINTER;
+}
+
+static inline gboolean
+mono_class_is_abstract (MonoClass *klass)
+{
+ return mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT;
+}
+
+static inline gboolean
+mono_class_is_interface (MonoClass *klass)
+{
+ return mono_class_get_flags (klass) & TYPE_ATTRIBUTE_INTERFACE;
+}
+
+static inline gboolean
+mono_class_is_sealed (MonoClass *klass)
+{
+ return mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SEALED;
+}
+
+static inline gboolean
+mono_class_is_before_field_init (MonoClass *klass)
+{
+ return mono_class_get_flags (klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT;
+}
+
+static inline gboolean
+mono_class_is_auto_layout (MonoClass *klass)
+{
+ return (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT;
+}
+
+static inline gboolean
+mono_class_is_explicit_layout (MonoClass *klass)
+{
+ return (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT;
+}
+
+static inline gboolean
+mono_class_is_public (MonoClass *klass)
+{
+ return mono_class_get_flags (klass) & TYPE_ATTRIBUTE_PUBLIC;
+}
+
+static inline gboolean
+mono_class_has_static_metadata (MonoClass *klass)
+{
+ return klass->type_token && !klass->image->dynamic && !mono_class_is_ginst (klass);
+}
+
+#endif
#define MONO_CLASS_IS_ARRAY(c) ((c)->rank)
-#define MONO_CLASS_HAS_STATIC_METADATA(klass) ((klass)->type_token && !(klass)->image->dynamic && !(klass)->generic_class)
+#define MONO_CLASS_HAS_STATIC_METADATA(klass) ((klass)->type_token && !(klass)->image->dynamic && !mono_class_is_ginst (klass))
#define MONO_DEFAULT_SUPERTABLE_SIZE 6
GList *nested_classes;
} MonoClassExt;
+typedef enum {
+ MONO_CLASS_DEF = 1, /* non-generic type */
+ MONO_CLASS_GTD, /* generic type definition */
+ MONO_CLASS_GINST, /* generic instantiation */
+ MONO_CLASS_GPARAM, /* generic parameter */
+ MONO_CLASS_ARRAY, /* vector or array, bounded or not */
+ MONO_CLASS_POINTER, /* pointer of function pointer*/
+} MonoTypeKind;
+
struct _MonoClass {
/* element class for arrays and enum basetype for enums */
MonoClass *element_class;
int instance_size; /* object instance size */
guint inited : 1;
- /* We use init_pending to detect cyclic calls to mono_class_init */
- guint init_pending : 1;
/* A class contains static and non static data. Static data can be
* of the same type as the class itselfs, but it does not influence
guint nested_classes_inited : 1; /* Whenever nested_class is initialized */
/* next byte*/
+ guint class_kind : 3; /* One of the values from MonoTypeKind */
guint interfaces_inited : 1; /* interfaces is initialized */
guint simd_type : 1; /* class is a simd intrinsic type */
- guint is_generic : 1; /* class is a generic type definition */
- guint is_inflated : 1; /* class is a generic instance */
guint has_finalize_inited : 1; /* has_finalize is initialized */
guint fields_inited : 1; /* setup_fields () has finished */
guint has_failure : 1; /* See MONO_CLASS_PROP_EXCEPTION_DATA for a MonoErrorBoxed with the details */
int vtable_size; /* number of slots */
guint16 interface_count;
- guint16 interface_id; /* unique inderface id (for interfaces) */
- guint16 max_interface_id;
+ guint32 interface_id; /* unique inderface id (for interfaces) */
+ guint32 max_interface_id;
guint16 interface_offsets_count;
MonoClass **interfaces_packed;
/*
* From the TypeDef table
*/
- guint32 flags;
struct {
#if MONO_SMALL_CONFIG
- guint16 first, count;
+ guint16 count;
#else
- guint32 first, count;
+ guint32 count;
+#endif
+ } field;
+ struct {
+#if MONO_SMALL_CONFIG
+ guint16 count;
+#else
+ guint32 count;
#endif
- } field, method;
+ } method;
/* A GC handle pointing to the corresponding type builder/generic param builder */
guint32 ref_info_handle;
MonoType this_arg;
MonoType byval_arg;
- MonoGenericClass *generic_class;
- MonoGenericContainer *generic_container;
-
MonoGCDescriptor gc_descr;
MonoClassRuntimeInfo *runtime_info;
- /* next element in the class_cache hash list (in MonoImage) */
- MonoClass *next_class_cache;
-
/* Generic vtable. Initialized by a call to mono_class_setup_vtable () */
MonoMethod **vtable;
MonoClassExt *ext;
};
+typedef struct {
+ MonoClass class;
+ guint32 flags;
+ /*
+ * From the TypeDef table
+ */
+ guint32 first_method_idx;
+ guint32 first_field_idx;
+ /* next element in the class_cache hash list (in MonoImage) */
+ MonoClass *next_class_cache;
+} MonoClassDef;
+
+typedef struct {
+ MonoClassDef class;
+ MonoGenericContainer *generic_container;
+} MonoClassGtd;
+
+typedef struct {
+ MonoClass class;
+ MonoGenericClass *generic_class;
+} MonoClassGenericInst;
+
+typedef struct {
+ MonoClass class;
+} MonoClassGenericParam;
+
+typedef struct {
+ MonoClass class;
+} MonoClassArray;
+
+typedef struct {
+ MonoClass class;
+} MonoClassPointer;
+
#ifdef COMPRESSED_INTERFACE_BITMAP
int mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size);
int mono_class_interface_match (const uint8_t *bitmap, int id);
MonoDomain *domain; /* each object/vtable belongs to exactly one domain */
gpointer type; /* System.Type type for klass */
guint8 *interface_bitmap;
- guint16 max_interface_id;
+ guint32 max_interface_id;
guint8 rank;
guint remote : 1; /* class is remotely activated */
guint initialized : 1; /* cctor has been run */
MonoGenericContainer*
mono_class_get_generic_container (MonoClass *klass);
-MonoGenericClass*
-mono_class_get_generic_class (MonoClass *klass);
-
gpointer
mono_class_alloc (MonoClass *klass, int size);
gboolean
mono_class_has_failure (const MonoClass *klass);
+/* Kind specific accessors */
+MonoGenericClass*
+mono_class_get_generic_class (MonoClass *klass);
+
+MonoGenericClass*
+mono_class_try_get_generic_class (MonoClass *klass);
+
+void
+mono_class_set_flags (MonoClass *klass, guint32 flags);
+
+MonoGenericContainer*
+mono_class_try_get_generic_container (MonoClass *klass);
+
+void
+mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container);
+
+guint32
+mono_class_get_first_method_idx (MonoClass *klass);
+
+void
+mono_class_set_first_method_idx (MonoClass *klass, guint32 idx);
+
+guint32
+mono_class_get_first_field_idx (MonoClass *klass);
+
+void
+mono_class_set_first_field_idx (MonoClass *klass, guint32 idx);
+
+/*Now that everything has been defined, let's include the inline functions */
+#include <mono/metadata/class-inlines.h>
+
#endif /* __MONO_METADATA_CLASS_INTERNALS_H__ */
gboolean mono_align_small_structs = FALSE;
/* Statistics */
-guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
-guint32 classes_size, class_ext_size;
+guint32 inflated_classes_size, inflated_methods_size;
+guint32 classes_size, class_ext_size, class_ext_count;
+guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
/* Low level lock which protects data structures in this module */
static mono_mutex_t classes_mutex;
/* This TLS variable points to a GSList of classes which have setup_fields () executing */
static MonoNativeTlsKey setup_fields_tls_id;
+static MonoNativeTlsKey init_pending_tls_id;
+
static inline void
classes_lock (void)
{
}
if (is_recursed)
break;
- if (klass->generic_class) {
- MonoGenericClass *gclass = klass->generic_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericClass *gclass = mono_class_get_generic_class (klass);
MonoGenericInst *inst = gclass->context.class_inst;
MonoTypeNameFormat nested_format;
int i;
g_string_append_c (str, '>');
else
g_string_append_c (str, ']');
- } else if (klass->generic_container &&
+ } else if (mono_class_is_gtd (klass) &&
(format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
(format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
int i;
g_string_append_c (str, '<');
else
g_string_append_c (str, '[');
- for (i = 0; i < klass->generic_container->type_argc; i++) {
+ for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
if (i)
g_string_append_c (str, ',');
- g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
+ g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
}
if (format == MONO_TYPE_NAME_FORMAT_IL)
g_string_append_c (str, '>');
return t->data.generic_class->context.class_inst->is_open;
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE:
- return t->data.klass->generic_container != NULL;
+ return mono_class_is_gtd (t->data.klass);
default:
return FALSE;
}
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE: {
MonoClass *klass = type->data.klass;
- MonoGenericContainer *container = klass->generic_container;
+ MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
MonoGenericInst *inst;
MonoGenericClass *gclass = NULL;
MonoType *nt;
MonoGenericContext *
mono_class_get_context (MonoClass *klass)
{
- return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
-}
-
-/*
- * mono_class_get_generic_container:
- *
- * Return the generic container of KLASS which should be a generic type definition.
- */
-MonoGenericContainer*
-mono_class_get_generic_container (MonoClass *klass)
-{
- g_assert (klass->is_generic);
-
- return klass->generic_container;
-}
-
-/*
- * mono_class_get_generic_class:
- *
- * Return the MonoGenericClass of KLASS, which should be a generic instance.
- */
-MonoGenericClass*
-mono_class_get_generic_class (MonoClass *klass)
-{
- g_assert (klass->is_inflated);
-
- return klass->generic_class;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ return gklass ? mono_generic_class_get_context (gklass) : NULL;
}
/*
*
*/
if (!((method->is_generic && context->method_inst) ||
- (method->klass->generic_container && context->class_inst)))
+ (mono_class_is_gtd (method->klass) && context->class_inst)))
return method;
iresult = g_new0 (MonoMethodInflated, 1);
iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
if (!context->class_inst) {
- g_assert (!iresult->declaring->klass->generic_class);
- if (iresult->declaring->klass->generic_container)
- iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
- else if (iresult->declaring->klass->generic_class)
- iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
+ g_assert (!mono_class_is_ginst (iresult->declaring->klass));
+ if (mono_class_is_gtd (iresult->declaring->klass))
+ iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
}
/* This can happen with some callers like mono_object_get_virtual_method () */
- if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
+ if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
iresult->context.class_inst = NULL;
MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
}
}
- if (!klass_hint || !klass_hint->generic_class ||
- klass_hint->generic_class->container_class != method->klass ||
- klass_hint->generic_class->context.class_inst != context->class_inst)
- klass_hint = NULL;
+ if (klass_hint) {
+ MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
+ if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
+ klass_hint = NULL;
+ }
- if (method->klass->generic_container)
+ if (mono_class_is_gtd (method->klass))
result->klass = klass_hint;
if (!result->klass) {
return NULL;
if (method->is_generic)
return &(mono_method_get_generic_container (method)->context);
- if (method->klass->generic_container)
- return &method->klass->generic_container->context;
+ if (mono_class_is_gtd (method->klass))
+ return &mono_class_get_generic_container (method->klass)->context;
return NULL;
}
MonoGenericContainer *container = NULL;
MonoImage *m = klass->image;
const int top = klass->field.count;
- int i;
+ int i, first_field_idx;
g_assert (klass->enumtype);
mono_error_init (error);
- if (klass->generic_container)
- container = klass->generic_container;
- else if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ container = mono_class_try_get_generic_container (klass);
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
- container = gklass->generic_container;
+ container = mono_class_get_generic_container (gklass);
g_assert (container);
}
/*
* Fetch all the field information.
*/
+ first_field_idx = mono_class_get_first_field_idx (klass);
for (i = 0; i < top; i++){
const char *sig;
guint32 cols [MONO_FIELD_SIZE];
- int idx = klass->field.first + i;
+ int idx = first_field_idx + i;
MonoType *ftype;
- /* klass->field.first and idx points into the fieldptr table */
+ /* first_field_idx and idx points into the fieldptr table */
mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
if (!ftype)
goto fail;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
//FIXME do we leak here?
ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
if (!mono_error_ok (error))
gpointer
mono_class_alloc (MonoClass *klass, int size)
{
- if (klass->generic_class)
- return mono_image_set_alloc (klass->generic_class->owner, size);
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass)
+ return mono_image_set_alloc (gklass->owner, size);
else
return mono_image_alloc (klass->image, size);
}
* Initializes the following fields in MonoClass:
* * klass->fields (only field->parent and field->name)
* * klass->field.count
- * * klass->field.first
+ * * klass->first_field_idx
* LOCKING: Acquires the loader lock
*/
static void
mono_class_setup_basic_field_info (MonoClass *klass)
{
+ MonoGenericClass *gklass;
MonoClassField *field;
MonoClassField *fields;
MonoClass *gtd;
if (klass->fields)
return;
- gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
+ gklass = mono_class_try_get_generic_class (klass);
+ gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
image = klass->image;
- if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
+
+ if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
/*
* This happens when a generic instance of an unfinished generic typebuilder
* is used as an element type for creating an array type. We can't initialize
mono_class_setup_basic_field_info (gtd);
mono_loader_lock ();
- klass->field.first = gtd->field.first;
klass->field.count = gtd->field.count;
mono_loader_unlock ();
}
/*
* Fetch all the field information.
*/
- for (i = 0; i < top; i++){
+ int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
+ for (i = 0; i < top; i++) {
field = &fields [i];
field->parent = klass;
if (gtd) {
field->name = mono_field_get_name (>d->fields [i]);
} else {
- int idx = klass->field.first + i;
- /* klass->field.first and idx points into the fieldptr table */
+ int idx = first_field_idx + i;
+ /* first_field_idx and idx points into the fieldptr table */
guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
/* The name is needed for fieldrefs */
field->name = mono_metadata_string_heap (image, name_idx);
* Initializes klass->fields, computes class layout and sizes.
* typebuilder_setup_fields () is the corresponding function for dynamic classes.
* Sets the following fields in @klass:
- * - packing_size
- * - min_align
- * - blittable
- * - has_references (if the class contains instance references firled or structs that contain references)
- * - has_static_refs (same, but for static fields)
- * - instance_size (size of the object in memory)
- * - class_size (size needed for the static fields)
- * - size_inited (flag set when the instance_size is set)
+ * - all the fields initialized by mono_class_init_sizes ()
* - element_class/cast_class (for enums)
+ * - field->type/offset for all fields
* - fields_inited
*
* LOCKING: Acquires the loader lock.
MonoError error;
MonoImage *m = klass->image;
int top;
- guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+ guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
int i;
guint32 real_size = 0;
guint32 packing_size = 0;
int instance_size;
gboolean explicit_size;
MonoClassField *field;
- MonoClass *gtd;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
if (klass->fields_inited)
return;
- if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
+ if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
/*
* This happens when a generic instance of an unfinished generic typebuilder
* is used as an element type for creating an array type. We can't initialize
mono_class_setup_basic_field_info (klass);
top = klass->field.count;
- gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
if (gtd) {
mono_class_setup_fields (gtd);
if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
/*
* Fetch all the field information.
*/
+ int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
for (i = 0; i < top; i++) {
- int idx = klass->field.first + i;
+ int idx = first_field_idx + i;
field = &klass->fields [i];
if (!field->type) {
mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
break;
}
- if (klass->generic_container) {
+ if (mono_class_is_gtd (klass)) {
mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
break;
}
mono_native_tls_set_value (setup_fields_tls_id, init_list);
}
+static void
+init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
+{
+ if (cached_info) {
+ klass->instance_size = cached_info->instance_size;
+ klass->sizes.class_size = cached_info->class_size;
+ klass->packing_size = cached_info->packing_size;
+ klass->min_align = cached_info->min_align;
+ klass->blittable = cached_info->blittable;
+ klass->has_references = cached_info->has_references;
+ klass->has_static_refs = cached_info->has_static_refs;
+ klass->no_special_static_fields = cached_info->no_special_static_fields;
+ }
+ else {
+ if (!klass->size_inited)
+ mono_class_setup_fields (klass);
+ }
+}
/*
- * mono_class_has_references:
+
+ * mono_class_init_sizes:
+ *
+ * Initializes the size related fields of @klass without loading all field data if possible.
+ * Sets the following fields in @klass:
+ * - instance_size
+ * - sizes.class_size
+ * - packing_size
+ * - min_align
+ * - blittable
+ * - has_references
+ * - has_static_refs
+ * - size_inited
+ * Can fail the class.
*
- * Returns whenever @klass->has_references is set, initializing it if needed.
- * Aquires the loader lock.
+ * LOCKING: Acquires the loader lock.
*/
-static gboolean
-mono_class_has_references (MonoClass *klass)
+static void
+mono_class_init_sizes (MonoClass *klass)
{
- if (klass->init_pending) {
- /* Be conservative */
- return TRUE;
- } else {
- mono_class_init (klass);
+ MonoCachedClassInfo cached_info;
+ gboolean has_cached_info;
- return klass->has_references;
- }
+ has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
+
+ init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
}
/*
return type;
}
+static gboolean
+class_has_references (MonoClass *klass)
+{
+ mono_class_init_sizes (klass);
+
+ /*
+ * has_references is not set if this is called recursively, but this is not a problem since this is only used
+ * during field layout, and instance fields are initialized before static fields, and instance fields can't
+ * embed themselves.
+ */
+ return klass->has_references;
+}
+
static gboolean
type_has_references (MonoClass *klass, MonoType *ftype)
{
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
return TRUE;
if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
MonoGenericParam *gparam = ftype->data.generic_param;
if (gparam->gshared_constraint)
- return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
+ return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
}
return FALSE;
}
{
int i;
const int top = klass->field.count;
- guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+ guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
guint32 pass, passes, real_size;
gboolean gc_aware_layout = FALSE;
gboolean has_static_fields = FALSE;
* Compute field layout and total size (not considering static fields)
*/
field_offsets = g_new0 (int, top);
+ int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
switch (layout) {
case TYPE_ATTRIBUTE_AUTO_LAYOUT:
case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
/* Already set by typebuilder_setup_fields () */
field_offsets [i] = field->offset + sizeof (MonoObject);
} else {
- int idx = klass->field.first + i;
+ int idx = first_field_idx + i;
guint32 offset;
mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
field_offsets [i] = offset + sizeof (MonoObject);
if (klass->methods)
return;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
MonoError error;
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
if (!mono_class_has_failure (gklass))
for (i = 0; i < klass->interface_count; i++)
setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
- } else {
+ } else if (mono_class_has_static_metadata (klass)) {
MonoError error;
+ int first_idx = mono_class_get_first_method_idx (klass);
count = klass->method.count;
methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
for (i = 0; i < count; ++i) {
- int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
+ int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
if (!methods [i]) {
mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
mono_error_cleanup (&error);
}
}
+ } else {
+ methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
+ count = 0;
}
if (MONO_CLASS_IS_INTERFACE (klass)) {
mono_class_get_method_by_index (MonoClass *klass, int index)
{
MonoError error;
+
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
/* Avoid calling setup_methods () if possible */
- if (klass->generic_class && !klass->methods) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (gklass && !klass->methods) {
MonoMethod *m;
m = mono_class_inflate_generic_method_full_checked (
- gklass->methods [index], klass, mono_class_get_context (klass), &error);
+ gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
/*
* If setup_methods () is called later for this class, no duplicates are created,
MonoMethod*
mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
{
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
int i;
g_assert (method->klass == gklass);
return klass->parent->vtable [offset];
}
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
MonoError error;
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_setup_vtable (gklass);
m = gklass->vtable [offset];
if (klass->ext && klass->ext->properties)
return;
- if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
mono_class_setup_properties (gklass);
properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
startm = mono_metadata_methods_from_property (klass->image, i, &endm);
+ int first_idx = mono_class_get_first_method_idx (klass);
for (j = startm; j < endm; ++j) {
MonoMethod *method;
method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
mono_error_cleanup (&error); /* FIXME don't swallow this error */
} else {
- method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
+ method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
}
switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
if (klass->ext && klass->ext->events)
return;
- if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
MonoGenericContext *context = NULL;
mono_class_setup_events (gklass);
event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
startm = mono_metadata_methods_from_event (klass->image, i, &endm);
+ int first_idx = mono_class_get_first_method_idx (klass);
for (j = startm; j < endm; ++j) {
MonoMethod *method;
method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
mono_error_cleanup (&error); /* FIXME don't swallow this error */
} else {
- method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
+ method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
}
switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
* LOCKING: Acquires the classes lock.
* Returns: The new ID.
*/
-static guint
+static guint32
mono_get_unique_iid (MonoClass *klass)
{
int iid;
}
mono_bitset_set (global_interface_bitset, iid);
/* set the bit also in the per-image set */
- if (!klass->generic_class) {
+ if (!mono_class_is_ginst (klass)) {
if (klass->image->interface_bitset) {
if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
if (mono_print_vtable) {
int generic_id;
char *type_name = mono_type_full_name (&klass->byval_arg);
- if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
- generic_id = klass->generic_class->context.class_inst->id;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass && !gklass->context.class_inst->is_open) {
+ generic_id = gklass->context.class_inst->id;
g_assert (generic_id != 0);
} else {
generic_id = 0;
}
#endif
- g_assert (iid <= 65535);
+ /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
+ * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
+ g_assert (iid < INT_MAX);
return iid;
}
valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
}
+static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
+static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
+static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
+static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
+static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
+
/* this won't be needed once bug #325495 is completely fixed
* though we'll need something similar to know which interfaces to allow
* in arrays when they'll be lazyly created
get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
{
MonoClass *eclass = klass->element_class;
- static MonoClass* generic_icollection_class = NULL;
- static MonoClass* generic_ienumerable_class = NULL;
- static MonoClass* generic_ienumerator_class = NULL;
- static MonoClass* generic_ireadonlylist_class = NULL;
- static MonoClass* generic_ireadonlycollection_class = NULL;
+ MonoClass* generic_icollection_class;
+ MonoClass* generic_ienumerable_class;
+ MonoClass* generic_ienumerator_class;
+ MonoClass* generic_ireadonlylist_class;
+ MonoClass* generic_ireadonlycollection_class;
MonoClass *valuetype_types[2] = { NULL, NULL };
MonoClass **interfaces = NULL;
int i, nifaces, interface_count, real_count, original_rank;
eclass_is_valuetype = FALSE;
original_rank = eclass->rank;
if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
- if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
/*
* For a Enumerator<T[]> we need to get the list of interfaces for T.
*/
- eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
original_rank = eclass->rank;
if (!eclass->rank)
eclass = eclass->element_class;
*/
all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
- if (!generic_icollection_class) {
- generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
- "System.Collections.Generic", "ICollection`1");
- generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
- "System.Collections.Generic", "IEnumerable`1");
- generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
- "System.Collections.Generic", "IEnumerator`1");
- generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
- "System.Collections.Generic", "IReadOnlyList`1");
- generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
- "System.Collections.Generic", "IReadOnlyCollection`1");
- }
+ generic_icollection_class = mono_class_get_generic_icollection_class ();
+ generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
+ generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
+ generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
+ generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
mono_class_init (eclass);
++count;
}
} else {
+ int first_idx = mono_class_get_first_method_idx (klass);
for (i = 0; i < klass->method.count; ++i) {
- flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
+ flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
if (flags & METHOD_ATTRIBUTE_VIRTUAL)
++count;
#endif
/*
- * LOCKING: this is supposed to be called with the loader lock held.
* Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
+ * LOCKING: Acquires the loader lock.
*/
static int
setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
{
MonoError error;
MonoClass *k, *ic;
- int i, j, max_iid, num_ifaces;
+ int i, j, num_ifaces;
+ guint32 max_iid;
MonoClass **interfaces_full = NULL;
int *interface_offsets_full = NULL;
GPtrArray *ifaces;
for (i = 0; i < k->interface_count; i++) {
ic = k->interfaces [i];
- if (!ic->inited)
- mono_class_init (ic);
+ mono_class_init (ic);
if (max_iid < ic->interface_id)
max_iid = ic->interface_id;
if (max_iid < klass->interface_id)
max_iid = klass->interface_id;
}
- klass->max_interface_id = max_iid;
+
/* compute vtable offset for interfaces */
interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
- for (i = 0; i < num_ifaces; i++) {
+ for (i = 0; i < num_ifaces; i++)
interface_offsets_full [i] = -1;
- }
/* skip the current class */
for (j = 0; j < klass->idepth - 1; j++) {
for (i = 0; i < num_array_interfaces; ++i) {
int offset;
ic = array_interfaces [i];
- if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
+ if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
offset = ilist_offset;
else if (strcmp (ic->name, "ICollection`1") == 0)
offset = icollection_offset;
}
for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
- if (interface_offsets_full [i] != -1) {
+ if (interface_offsets_full [i] != -1)
interface_offsets_count ++;
- }
}
+ /* Publish the data */
+ mono_loader_lock ();
+
+ klass->max_interface_id = max_iid;
/*
* We might get called multiple times:
* - mono_class_init ()
bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
#endif
for (i = 0; i < interface_offsets_count; i++) {
- int id = interfaces_full [i]->interface_id;
+ guint32 id = interfaces_full [i]->interface_id;
bitmap [id >> 3] |= (1 << (id & 7));
klass->interfaces_packed [i] = interfaces_full [i];
klass->interface_offsets_packed [i] = interface_offsets_full [i];
klass->interface_bitmap = bitmap;
#endif
}
+ mono_loader_unlock ();
end:
g_free (interfaces_full);
//printf ("JUST DONE: ");
//print_implemented_interfaces (klass);
-
+
return cur_slot;
}
void
mono_class_setup_interface_offsets (MonoClass *klass)
{
- mono_loader_lock ();
-
setup_interface_offsets (klass, 0, FALSE);
-
- mono_loader_unlock ();
}
/*Checks if @klass has @parent as one of it's parents type gtd
{
MonoGenericInst *ginst;
int i;
- if (!klass->generic_class) {
+
+ if (!mono_class_is_ginst (klass)) {
mono_class_setup_vtable_full (klass, in_setup);
return !mono_class_has_failure (klass);
}
mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
- if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable"))
+ if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
return FALSE;
- ginst = klass->generic_class->context.class_inst;
+ ginst = mono_class_get_generic_class (klass)->context.class_inst;
for (i = 0; i < ginst->type_argc; ++i) {
MonoClass *arg;
if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
mono_stats.generic_vtable_count ++;
in_setup = g_list_prepend (in_setup, klass);
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
if (!mono_class_check_vtable_constraints (klass, in_setup)) {
mono_loader_unlock ();
g_list_remove (in_setup, klass);
}
context = mono_class_get_context (klass);
- type_token = klass->generic_class->container_class->type_token;
+ type_token = mono_class_get_generic_class (klass)->container_class->type_token;
} else {
- context = (MonoGenericContext *) klass->generic_container;
+ context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
type_token = klass->type_token;
}
MonoError error;
MonoClass *k, *ic;
MonoMethod **vtable;
- int i, max_vtsize = 0, max_iid, cur_slot = 0;
+ int i, max_vtsize = 0, cur_slot = 0;
+ guint32 max_iid;
GPtrArray *ifaces = NULL;
GHashTable *override_map = NULL;
MonoMethod *cm;
DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
/* Optimized version for generic instances */
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
MonoError error;
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
MonoMethod **tmp;
mono_class_setup_vtable_full (gklass, in_setup);
// it can happen (for injected generic array interfaces) that the same slot is
// processed multiple times (those interfaces have overlapping slots), and it
// will not always be the first pass the one that fills the slot.
- if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ if (!mono_class_is_abstract (klass)) {
for (i = 0; i < klass->interface_offsets_count; i++) {
int ic_offset;
int im_index;
virt_methods = NULL;
/* Ensure that all vtable slots are filled with concrete instance methods */
- if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ if (!mono_class_is_abstract (klass)) {
for (i = 0; i < cur_slot; ++i) {
if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
char *type_name = mono_type_get_full_name (klass);
}
}
- if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
MonoClass *gklass;
int i;
- if (!method->klass->generic_class) {
+ if (!mono_class_is_ginst (method->klass)) {
g_assert (method->is_inflated);
return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
}
/* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
- g_assert (method->klass->generic_class);
- gklass = method->klass->generic_class->container_class;
+ g_assert (mono_class_is_ginst (method->klass));
+ gklass = mono_class_get_generic_class (method->klass)->container_class;
mono_class_setup_methods (method->klass);
g_assert (method->klass->methods);
for (i = 0; i < method->klass->method.count; ++i) {
int i;
tmp_context.class_inst = NULL;
- tmp_context.method_inst = iface->generic_class->context.class_inst;
+ tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
//g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
for (i = 0; i < generic_array_method_num; i++) {
/**
* mono_class_init:
- * @class: the class to initialize
+ * @klass: the class to initialize
*
* Compute the instance_size, class_size and other infos that cannot be
* computed at mono_class_get() time. Also compute vtable_size if possible.
* Returns TRUE on success or FALSE if there was a problem in loading
- * the type (incorrect assemblies, missing assemblies, methods, etc).
+ * the type (incorrect assemblies, missing assemblies, methods, etc).
+ * Initializes the following fields in @klass:
+ * - all the fields initialized by mono_class_init_sizes ()
+ * - has_cctor
+ * - ghcimpl
+ * - inited
*
* LOCKING: Acquires the loader lock.
*/
gboolean
mono_class_init (MonoClass *klass)
{
- int i;
+ int i, vtable_size = 0, array_method_count = 0;
MonoCachedClassInfo cached_info;
gboolean has_cached_info;
+ gboolean locked = FALSE;
+ gboolean ghcimpl = FALSE;
+ gboolean has_cctor = FALSE;
+ int first_iface_slot = 0;
g_assert (klass);
/*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
- /* We do everything inside the lock to prevent races */
- mono_loader_lock ();
-
- if (klass->inited || mono_class_has_failure (klass)) {
- mono_loader_unlock ();
- /* Somebody might have gotten in before us */
- return !mono_class_has_failure (klass);
- }
-
- if (klass->init_pending) {
+ /*
+ * This function can recursively call itself.
+ */
+ GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
+ if (g_slist_find (init_list, klass)) {
mono_class_set_type_load_failure (klass, "Recursive type definition detected");
goto leave;
}
+ init_list = g_slist_prepend (init_list, klass);
+ mono_native_tls_set_value (init_pending_tls_id, init_list);
- klass->init_pending = 1;
+ /*
+ * We want to avoid doing complicated work inside locks, so we compute all the required
+ * information and write it to @klass inside a lock.
+ */
if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
goto leave;
}
-
if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
MonoClass *element_class = klass->element_class;
if (!element_class->inited)
mono_stats.initialized_class_count++;
- if (klass->generic_class && !klass->generic_class->is_dynamic) {
- MonoClass *gklass = klass->generic_class->container_class;
-
- mono_stats.generic_class_count++;
-
- klass->method = gklass->method;
- klass->field = gklass->field;
+ if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
- // FIXME: Why is this needed ?
- if (!mono_class_has_failure (gklass))
- mono_class_setup_methods (gklass);
if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
goto leave;
- if (MONO_CLASS_IS_INTERFACE (klass))
- klass->interface_id = mono_get_unique_iid (klass);
+ mono_class_setup_interface_id (klass);
}
if (klass->parent && !klass->parent->inited)
has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
- if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
- klass->nested_classes_inited = TRUE;
-
- /*
- * Computes the size used by the fields, and their locations
- */
- if (has_cached_info) {
- klass->instance_size = cached_info.instance_size;
- klass->sizes.class_size = cached_info.class_size;
- klass->packing_size = cached_info.packing_size;
- klass->min_align = cached_info.min_align;
- klass->blittable = cached_info.blittable;
- klass->has_references = cached_info.has_references;
- klass->has_static_refs = cached_info.has_static_refs;
- klass->no_special_static_fields = cached_info.no_special_static_fields;
- }
- else
- if (!klass->size_inited){
- mono_class_setup_fields (klass);
- if (mono_class_has_failure (klass))
- goto leave;
- }
-
- /* Initialize arrays */
- if (klass->rank) {
- klass->method.count = 3 + (klass->rank > 1? 2: 1);
-
- if (klass->interface_count) {
- int count_generic = generic_array_methods (klass);
- klass->method.count += klass->interface_count * count_generic;
- }
- }
+ /* Compute instance size etc. */
+ init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
+ if (mono_class_has_failure (klass))
+ goto leave;
mono_class_setup_supertypes (klass);
*/
if (has_cached_info) {
/* AOT case */
- klass->vtable_size = cached_info.vtable_size;
- klass->has_finalize = cached_info.has_finalize;
- klass->has_finalize_inited = TRUE;
- klass->ghcimpl = cached_info.ghcimpl;
- klass->has_cctor = cached_info.has_cctor;
+ vtable_size = cached_info.vtable_size;
+ ghcimpl = cached_info.ghcimpl;
+ has_cctor = cached_info.has_cctor;
} else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
/* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
* The first slot if for array with.
if (!szarray_vtable_size [slot]) {
mono_class_setup_vtable (klass);
szarray_vtable_size [slot] = klass->vtable_size;
+ vtable_size = klass->vtable_size;
} else {
- klass->vtable_size = szarray_vtable_size[slot];
+ vtable_size = szarray_vtable_size[slot];
}
- } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
- MonoClass *gklass = klass->generic_class->container_class;
+ } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
/* Generic instance case */
- klass->ghcimpl = gklass->ghcimpl;
- klass->has_cctor = gklass->has_cctor;
+ ghcimpl = gklass->ghcimpl;
+ has_cctor = gklass->has_cctor;
mono_class_setup_vtable (gklass);
if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
goto leave;
- klass->vtable_size = gklass->vtable_size;
+ vtable_size = gklass->vtable_size;
} else {
/* General case */
if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
MonoMethod *cmethod = NULL;
- if (klass->type_token && !image_is_dynamic(klass->image)) {
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
+
+ /* Generic instance case */
+ ghcimpl = gklass->ghcimpl;
+ has_cctor = gklass->has_cctor;
+ } else if (klass->type_token && !image_is_dynamic(klass->image)) {
cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
/* The find_method function ignores the 'flags' argument */
if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
- klass->has_cctor = 1;
+ has_cctor = 1;
} else {
mono_class_setup_methods (klass);
if (mono_class_has_failure (klass))
MonoMethod *method = klass->methods [i];
if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
(strcmp (".cctor", method->name) == 0)) {
- klass->has_cctor = 1;
+ has_cctor = 1;
break;
}
}
}
}
- if (klass->parent) {
- MonoError parent_error;
- mono_error_init (&parent_error);
- int first_iface_slot;
- /* This will compute klass->parent->vtable_size for some classes */
- mono_class_init (klass->parent);
- if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to initialize")) {
- goto leave;
+ if (klass->rank) {
+ array_method_count = 3 + (klass->rank > 1? 2: 1);
+
+ if (klass->interface_count) {
+ int count_generic = generic_array_methods (klass);
+ array_method_count += klass->interface_count * count_generic;
}
- if (!klass->parent->vtable_size) {
- /* FIXME: Get rid of this somehow */
+ }
+
+ if (klass->parent) {
+ if (!klass->parent->vtable_size)
mono_class_setup_vtable (klass->parent);
- if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize")) {
- goto leave;
- }
- }
+ if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
+ goto leave;
+ g_assert (klass->parent->vtable_size);
first_iface_slot = klass->parent->vtable_size;
if (mono_class_need_stelemref_method (klass))
++first_iface_slot;
- setup_interface_offsets (klass, first_iface_slot, TRUE);
- } else {
- setup_interface_offsets (klass, 0, TRUE);
}
+ /*
+ * Do the actual changes to @klass inside the loader lock
+ */
+ mono_loader_lock ();
+ locked = TRUE;
+
+ if (klass->inited || mono_class_has_failure (klass)) {
+ mono_loader_unlock ();
+ /* Somebody might have gotten in before us */
+ return !mono_class_has_failure (klass);
+ }
+
+ mono_stats.initialized_class_count++;
+
+ if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
+
+ mono_stats.generic_class_count++;
+
+ klass->method = gklass->method;
+ klass->field = gklass->field;
+ }
+
+ if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
+ klass->nested_classes_inited = TRUE;
+ klass->ghcimpl = ghcimpl;
+ klass->has_cctor = has_cctor;
+ if (vtable_size)
+ klass->vtable_size = vtable_size;
+ if (has_cached_info) {
+ klass->has_finalize = cached_info.has_finalize;
+ klass->has_finalize_inited = TRUE;
+ }
+ if (klass->rank)
+ klass->method.count = array_method_count;
+
+ mono_loader_unlock ();
+ locked = FALSE;
+
+ setup_interface_offsets (klass, first_iface_slot, TRUE);
+
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_inheritance (klass);
- if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
+ if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
goto leave;
leave:
+ init_list = g_slist_remove (init_list, klass);
+ mono_native_tls_set_value (init_pending_tls_id, init_list);
+
/* Because of the double-checking locking pattern */
mono_memory_barrier ();
klass->inited = 1;
- klass->init_pending = 0;
- mono_loader_unlock ();
+ if (locked)
+ mono_loader_unlock ();
return !mono_class_has_failure (klass);
}
MonoMethod *cmethod = NULL;
if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
- } else if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ } else if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
has_finalize = mono_class_has_finalizer (gklass);
} else if (klass->parent && klass->parent->has_finalize) {
if (MONO_CLASS_IS_INTERFACE (klass))
klass->interface_id = mono_get_unique_iid (klass);
-
}
#ifndef DISABLE_COM
klass->parent = parent;
- if (parent->generic_class && !parent->name) {
+ if (mono_class_is_ginst (parent) && !parent->name) {
/*
* If the parent is a generic instance, we may get
* called before it is fully initialized, especially
{
MonoClass *gtd = (MonoClass*)user_data;
/* Only try to fix generic instances of @gtd */
- if (gclass->generic_class->container_class != gtd)
+ if (mono_class_get_generic_class (gclass)->container_class != gtd)
return FALSE;
/* Check if the generic instance has no parent. */
name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
- klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
+ if (mono_metadata_has_generic_params (image, type_token)) {
+ klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
+ klass->class_kind = MONO_CLASS_GTD;
+ classes_size += sizeof (MonoClassGtd);
+ ++class_gtd_count;
+ } else {
+ klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
+ klass->class_kind = MONO_CLASS_DEF;
+ classes_size += sizeof (MonoClassDef);
+ ++class_def_count;
+ }
klass->name = name;
klass->name_space = nspace;
klass->image = image;
klass->type_token = type_token;
- klass->flags = cols [MONO_TYPEDEF_FLAGS];
+ mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
- classes_size += sizeof (MonoClass);
-
/*
* Check whether we're a generic type definition.
*/
- klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
- if (klass->generic_container) {
- klass->is_generic = 1;
- klass->generic_container->owner.klass = klass;
- klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
- context = &klass->generic_container->context;
- }
-
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass)) {
+ MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
+ generic_container->owner.klass = klass;
+ generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
+ context = &generic_container->context;
+ mono_class_set_generic_container (klass, generic_container);
enable_gclass_recording ();
+ }
if (cols [MONO_TYPEDEF_EXTENDS]) {
MonoClass *tmp;
mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
goto parent_failure;
}
- if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
+ if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
goto parent_failure;
}
/* uses ->valuetype, which is initialized by mono_class_setup_parent above */
mono_class_setup_mono_type (klass);
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
/*
}
}
- if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
klass->unicode = 1;
#ifdef HOST_WIN32
- if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
klass->unicode = 1;
#endif
return NULL;
}
+ /* This is required now that it is possible for more than 2^16 interfaces to exist. */
+ g_assert(icount <= 65535);
+
klass->interfaces = interfaces;
klass->interface_count = icount;
klass->interfaces_inited = 1;
/*
* Compute the field and method lists
*/
- klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
- klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
+ int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
+ mono_class_set_first_field_idx (klass, first_field_idx);
+ int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
+ mono_class_set_first_method_idx (klass, first_method_idx);
if (tt->rows > tidx){
mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
if (cols [MONO_TYPEDEF_FIELD_LIST] &&
cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
- klass->field.count = field_last - klass->field.first;
+ klass->field.count = field_last - first_field_idx;
else
klass->field.count = 0;
if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
- klass->method.count = method_last - klass->method.first;
+ klass->method.count = method_last - first_method_idx;
else
klass->method.count = 0;
* We must do this after the class has been constructed to make certain recursive scenarios
* work.
*/
- if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
+ if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
gboolean
mono_class_is_nullable (MonoClass *klass)
{
- return klass->generic_class != NULL &&
- klass->generic_class->container_class == mono_defaults.generic_nullable_class;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
}
mono_class_get_nullable_param (MonoClass *klass)
{
g_assert (mono_class_is_nullable (klass));
- return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
}
static void
{
if (gtd->parent) {
MonoError error;
- MonoGenericClass *gclass = klass->generic_class;
+ MonoGenericClass *gclass = mono_class_get_generic_class (klass);
klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
if (!mono_error_ok (&error)) {
return gclass->cached_class;
}
- klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
+ klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
gklass = gclass->container_class;
mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
klass->image = gklass->image;
- klass->flags = gklass->flags;
klass->type_token = gklass->type_token;
klass->field.count = gklass->field.count;
- klass->is_inflated = 1;
- klass->generic_class = gclass;
+ klass->class_kind = MONO_CLASS_GINST;
+ //FIXME add setter
+ ((MonoClassGenericInst*)klass)->generic_class = gclass;
klass->byval_arg.type = MONO_TYPE_GENERICINST;
klass->this_arg.type = klass->byval_arg.type;
mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
- inflated_classes ++;
- inflated_classes_size += sizeof (MonoClass);
+ ++class_ginst_count;
+ inflated_classes_size += sizeof (MonoClassGenericInst);
mono_loader_unlock ();
gboolean is_mvar = container->is_method;
gboolean is_anonymous = container->is_anonymous;
- klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
- classes_size += sizeof (MonoClass);
+ klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
+ klass->class_kind = MONO_CLASS_GPARAM;
+ classes_size += sizeof (MonoClassGenericParam);
+ ++class_gparam_count;
if (pinfo) {
CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
klass->inited = TRUE;
CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
- klass->flags = TYPE_ATTRIBUTE_PUBLIC;
klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
klass->this_arg.type = klass->byval_arg.type;
}
mono_image_unlock (image);
- result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
+ result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
- classes_size += sizeof (MonoClass);
+ classes_size += sizeof (MonoClassPointer);
+ ++class_pointer_count;
result->parent = NULL; /* no parent for PTR types */
result->name_space = el_class->name_space;
name = g_strdup_printf ("%s*", el_class->name);
result->name = mono_image_strdup (image, name);
+ result->class_kind = MONO_CLASS_POINTER;
g_free (name);
mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
result->image = el_class->image;
result->inited = TRUE;
- result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
result->cast_class = result->element_class = el_class;
result->blittable = TRUE;
}
result = g_new0 (MonoClass, 1);
+ classes_size += sizeof (MonoClassPointer);
+ ++class_pointer_count;
+
result->parent = NULL; /* no parent for PTR types */
result->name_space = "System";
result->name = "MonoFNPtrFakeClass";
+ result->class_kind = MONO_CLASS_POINTER;
mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
result->image = mono_defaults.corlib; /* need to fix... */
result->inited = TRUE;
- result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
result->cast_class = result->element_class = result;
result->blittable = TRUE;
if (!parent->inited)
mono_class_init (parent);
- klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
+ klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
klass->image = image;
klass->name_space = eclass->name_space;
+ klass->class_kind = MONO_CLASS_ARRAY;
+
nsize = strlen (eclass->name);
name = (char *)g_malloc (nsize + 2 + rank + 1);
memcpy (name, eclass->name, nsize);
mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
- classes_size += sizeof (MonoClass);
+ classes_size += sizeof (MonoClassArray);
+ ++class_array_count;
klass->type_token = 0;
- /* all arrays are marked serializable and sealed, bug #42779 */
- klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
klass->parent = parent;
klass->instance_size = mono_class_instance_size (klass->parent);
mono_class_setup_supertypes (klass);
- if (eclass->generic_class)
+ if (mono_class_is_ginst (eclass))
mono_class_init (eclass);
if (!eclass->size_inited)
mono_class_setup_fields (eclass);
klass->this_arg = klass->byval_arg;
klass->this_arg.byref = 1;
- klass->generic_container = eclass->generic_container;
+ //WTF was this? it's wrong
+ // klass->generic_container = eclass->generic_container;
if (rank == 1 && !bounded) {
MonoClass *prev_class;
*
* Use to get the computed minimum alignment requirements for the specified class.
*
- * Returns: minimm alignment requirements
+ * Returns: minimum alignment requirements
*/
gint32
mono_class_min_align (MonoClass *klass)
* Returns: the size of a value of kind @klass
*/
gint32
-mono_class_value_size (MonoClass *klass, guint32 *align)
+mono_class_value_size (MonoClass *klass, guint32 *align)
{
gint32 size;
return NULL;
while (klass) {
+ int first_field_idx = mono_class_get_first_field_idx (klass);
if (klass->image->uncompressed_metadata) {
/*
- * klass->field.first points to the FieldPtr table, while idx points into the
+ * first_field_idx points to the FieldPtr table, while idx points into the
* Field table, so we have to do a search.
*/
/*FIXME this is broken for types with multiple fields with the same name.*/
g_assert_not_reached ();
} else {
if (klass->field.count) {
- if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
- return &klass->fields [idx - klass->field.first];
+ if ((idx >= first_field_idx) && (idx < first_field_idx + klass->field.count)){
+ return &klass->fields [idx - first_field_idx];
}
}
}
while (klass) {
if (!klass->fields)
return 0;
+ int first_field_idx = mono_class_get_first_field_idx (klass);
for (i = 0; i < klass->field.count; ++i) {
if (&klass->fields [i] == field) {
- int idx = klass->field.first + i + 1;
+ int idx = first_field_idx + i + 1;
if (klass->image->uncompressed_metadata)
idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
int i;
MonoGenericContainer *container;
- if (!klass->generic_class)
+ if (!mono_class_is_ginst (klass))
return FALSE;
- container = klass->generic_class->container_class->generic_container;
+ container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
for (i = 0; i < container->type_argc; ++i)
if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
int j;
MonoType **klass_argv, **oklass_argv;
MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
- MonoGenericContainer *container = klass_gtd->generic_container;
+ MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
if (klass == oklass)
return TRUE;
if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
return FALSE;
- klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
- oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
+ klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
+ oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
for (j = 0; j < container->type_argc; ++j) {
MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
int j;
MonoType **klass_argv, **oklass_argv;
MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
- MonoGenericContainer *container = klass_gtd->generic_container;
+ MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
/*Viable candidates are instances of the same generic interface*/
if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
return FALSE;
- klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
- oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
+ klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
+ oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
for (j = 0; j < container->type_argc; ++j) {
MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
return result;
}
- if (klass->generic_class && !klass->methods)
- return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
+ if (mono_class_is_ginst (klass) && !klass->methods)
+ return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
}
return klass->rank;
}
-/**
- * mono_class_get_flags:
- * @klass: the MonoClass to act on
- *
- * The type flags from the TypeDef table from the metadata.
- * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
- * different values.
- *
- * Returns: The flags from the TypeDef table.
- */
-guint32
-mono_class_get_flags (MonoClass *klass)
-{
- return klass->flags;
-}
-
/**
* mono_class_get_name
* @klass: the MonoClass to act on
start_index = GPOINTER_TO_UINT (*iter);
}
+ int first_idx = mono_class_get_first_method_idx (klass);
for (i = start_index; i < klass->method.count; ++i) {
guint32 flags;
- /* klass->method.first points into the methodptr table */
- flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
+ /* first_idx points into the methodptr table */
+ flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
if (flags & METHOD_ATTRIBUTE_VIRTUAL)
break;
if (i < klass->method.count) {
MonoError error;
- res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
+ res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
mono_error_cleanup (&error); /* FIXME don't swallow the error */
/* Add 1 here so the if (*iter) check fails */
field_index = mono_field_get_index (field);
if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
- mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
+ int first_field_idx = mono_class_get_first_field_idx (klass);
+ mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
if (!rva)
g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
int i;
/* Search directly in the metadata to avoid calling setup_methods () */
+ int first_idx = mono_class_get_first_method_idx (klass);
for (i = 0; i < klass->method.count; ++i) {
MonoError error;
guint32 cols [MONO_METHOD_SIZE];
MonoMethod *method;
MonoMethodSignature *sig;
- /* klass->method.first points into the methodptr table */
- mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
+ /* first_idx points into the methodptr table */
+ mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
- method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
+ method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
if (!method) {
mono_error_cleanup (&error); /* FIXME don't swallow the error */
continue;
mono_class_init (klass);
- if (klass->generic_class && !klass->methods) {
- res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
+ if (mono_class_is_ginst (klass) && !klass->methods) {
+ res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
if (res) {
MonoError error;
res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
mono_os_mutex_init (&classes_mutex);
mono_native_tls_alloc (&setup_fields_tls_id, NULL);
-
+ mono_native_tls_alloc (&init_pending_tls_id, NULL);
+
+ mono_counters_register ("MonoClassDef count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
+ mono_counters_register ("MonoClassGtd count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
+ mono_counters_register ("MonoClassGenericInst count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
+ mono_counters_register ("MonoClassGenericParam count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
+ mono_counters_register ("MonoClassArray count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
+ mono_counters_register ("MonoClassPointer count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
mono_counters_register ("Inflated methods size",
MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
- mono_counters_register ("Inflated classes",
- MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
mono_counters_register ("Inflated classes size",
MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
mono_counters_register ("MonoClass size",
MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
mono_counters_register ("MonoClassExt size",
MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
+
+ mono_counters_register ("MonoClassExt count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
}
/**
mono_classes_cleanup (void)
{
mono_native_tls_free (setup_fields_tls_id);
+ mono_native_tls_free (init_pending_tls_id);
if (global_interface_bitset)
mono_bitset_free (global_interface_bitset);
MonoClass *
mono_class_get_generic_type_definition (MonoClass *klass)
{
- return klass->generic_class ? klass->generic_class->container_class : klass;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ return gklass ? gklass->container_class : klass;
}
/*
get_generic_definition_class (MonoClass *klass)
{
while (klass) {
- if (klass->generic_class && klass->generic_class->container_class)
- return klass->generic_class->container_class;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass && gklass->container_class)
+ return gklass->container_class;
klass = klass->parent;
}
return NULL;
if (member_klass->element_class && !member_klass->enumtype)
member_klass = member_klass->element_class;
- access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
return TRUE;
- if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
+ if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
return FALSE;
if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
return TRUE;
- if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
- access_klass->generic_container) &&
+ MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
+ if (((access_gklass && access_gklass->container_class) ||
+ mono_class_is_gtd (access_klass)) &&
(member_generic_def = get_generic_definition_class (member_klass))) {
MonoClass *access_container;
- if (access_klass->generic_container)
+ if (mono_class_is_gtd (access_klass))
access_container = access_klass;
else
- access_container = access_klass->generic_class->container_class;
+ access_container = access_gklass->container_class;
if (can_access_member (access_container, member_generic_def, context_klass, access_level))
return TRUE;
* FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
* FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
*/
-gboolean mono_class_is_valid_enum (MonoClass *klass) {
+gboolean
+mono_class_is_valid_enum (MonoClass *klass)
+{
MonoClassField * field;
gpointer iter = NULL;
gboolean found_base_field = FALSE;
return FALSE;
}
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if (!mono_class_is_auto_layout (klass))
return FALSE;
while ((field = mono_class_get_fields (klass, &iter))) {
gboolean
mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
{
- return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
+ return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
}
/*
if (!klass->ext)
klass->ext = ext;
class_ext_size += sizeof (MonoClassExt);
+ ++class_ext_count;
mono_image_unlock (klass->image);
}
if (interface_count > 1)
interfaces [1] = mono_class_bind_generic_parameters (
mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
- } else if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ } else if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_setup_interfaces (gklass, error);
if (!mono_error_ok (error)) {
interface_count = gklass->interface_count;
interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
for (i = 0; i < interface_count; i++) {
- interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
+ interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
if (!mono_error_ok (error)) {
mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
return;
{
MonoClass *klass = field->parent;
MonoImage *image = klass->image;
- MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
+ MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
int field_idx = field - klass->fields;
mono_error_init (error);
MonoClassField *gfield = >d->fields [field_idx];
MonoType *gtype = mono_field_get_type_checked (gfield, error);
if (!mono_error_ok (error)) {
- mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
+ char *full_name = mono_type_get_full_name (gtd);
+ mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
+ g_free (full_name);
}
field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
if (!mono_error_ok (error)) {
- mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
+ char *full_name = mono_type_get_full_name (klass);
+ mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
+ g_free (full_name);
}
} else {
const char *sig;
guint32 cols [MONO_FIELD_SIZE];
MonoGenericContainer *container = NULL;
- int idx = klass->field.first + field_idx;
+ int idx = mono_class_get_first_field_idx (klass) + field_idx;
/*FIXME, in theory we do not lazy load SRE fields*/
g_assert (!image_is_dynamic (image));
- if (klass->generic_container) {
- container = klass->generic_container;
+ if (mono_class_is_gtd (klass)) {
+ container = mono_class_get_generic_container (klass);
} else if (gtd) {
- container = gtd->generic_container;
+ container = mono_class_get_generic_container (gtd);
g_assert (container);
}
- /* klass->field.first and idx points into the fieldptr table */
+ /* first_field_idx and idx points into the fieldptr table */
mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
- mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
+ char *full_name = mono_type_get_full_name (klass);
+ mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
+ g_free (full_name);
return;
}
field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
if (!field->type) {
- mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
+ char *full_name = mono_type_get_full_name (klass);
+ mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
+ g_free (full_name);
}
}
}
{
MonoClass *klass = field->parent;
MonoImage *image = klass->image;
- MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
+ MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
int field_idx = field - klass->fields;
MonoClassField *gfield = >d->fields [field_idx];
return mono_field_get_flags (gfield);
} else {
- int idx = klass->field.first + field_idx;
+ int idx = mono_class_get_first_field_idx (klass) + field_idx;
/*FIXME, in theory we do not lazy load SRE fields*/
g_assert (!image_is_dynamic (image));
static gboolean cominterop_can_support_dispatch (MonoClass* klass)
{
- if (!(klass->flags & TYPE_ATTRIBUTE_PUBLIC) )
+ if (!mono_class_is_public (klass))
return FALSE;
if (!cominterop_com_visible (klass))
MonoCustomAttrInfo*
mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs);
+typedef gboolean (*MonoAssemblyMetadataCustomAttrIterFunc) (MonoImage *image, guint32 typeref_scope_token, const gchar* nspace, const gchar* name, guint32 method_token, gpointer user_data);
+
+void
+mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data);
+
#endif /* __MONO_METADATA_REFLECTION_CUSTOM_ATTRS_INTERNALS_H__ */
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
+#include "mono/metadata/assembly.h"
#include "mono/metadata/gc-internals.h"
#include "mono/metadata/mono-endian.h"
#include "mono/metadata/object-internals.h"
/* FIXME: Need to do more checks */
if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
- int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ int visibility = mono_class_get_flags (cattr->ctor->method->klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
return FALSE;
for (i = 0; i < klass->field.count; ++i) {
if (field == &klass->fields [i])
- return klass->field.first + 1 + i;
+ return mono_class_get_first_field_idx (klass) + 1 + i;
}
return 0;
}
mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
{
MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
+ MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, FALSE, &error);
mono_error_cleanup (&error);
return result;
}
* Returns: NULL if no attributes are found. On error returns NULL and sets @error.
*/
MonoCustomAttrInfo*
-mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
+mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ignore_missing, MonoError *error)
{
guint32 mtoken, i, len;
guint32 cols [MONO_CUSTOM_ATTR_SIZE];
attr = &ainfo->attrs [i - 1];
attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
if (!attr->ctor) {
- g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
- g_list_free (list);
- g_free (ainfo);
- return NULL;
+ g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, mtoken, mono_error_get_message (error));
+ if (ignore_missing) {
+ mono_error_cleanup (error);
+ mono_error_init (error);
+ } else {
+ g_list_free (list);
+ g_free (ainfo);
+ return NULL;
+ }
}
if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
idx = mono_method_get_index (method);
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_METHODDEF;
- return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
+ return mono_custom_attrs_from_index_checked (method->klass->image, idx, FALSE, error);
}
MonoCustomAttrInfo*
mono_error_init (error);
- if (klass->generic_class)
- klass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ klass = mono_class_get_generic_class (klass)->container_class;
if (image_is_dynamic (klass->image))
return lookup_custom_attr (klass->image, klass);
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_TYPEDEF;
}
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+ return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
}
MonoCustomAttrInfo*
mono_custom_attrs_from_assembly (MonoAssembly *assembly)
{
MonoError error;
- MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
+ MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, FALSE, &error);
mono_error_cleanup (&error);
return result;
}
MonoCustomAttrInfo*
-mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
+mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error)
{
guint32 idx;
idx = 1; /* there is only one assembly */
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
- return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
+ return mono_custom_attrs_from_index_checked (assembly->image, idx, ignore_missing, error);
}
static MonoCustomAttrInfo*
idx = 1; /* there is only one module */
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_MODULE;
- return mono_custom_attrs_from_index_checked (image, idx, error);
+ return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
}
MonoCustomAttrInfo*
idx = find_property_index (klass, property);
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_PROPERTY;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+ return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
}
MonoCustomAttrInfo*
idx = find_event_index (klass, event);
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_EVENT;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+ return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
}
MonoCustomAttrInfo*
idx = find_field_index (klass, field);
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_FIELDDEF;
- return mono_custom_attrs_from_index_checked (klass->image, idx, error);
+ return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
}
/**
idx = i;
idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= MONO_CUSTOM_ATTR_PARAMDEF;
- return mono_custom_attrs_from_index_checked (image, idx, error);
+ return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
}
gboolean
return_val_if_nok (error, NULL);
} else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
- cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
+ cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, FALSE, error);
return_val_if_nok (error, NULL);
} else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
MonoReflectionModule *module = (MonoReflectionModule*)obj;
return result;
}
+
+static gboolean
+custom_attr_class_name_from_methoddef (MonoImage *image, guint32 method_token, const gchar **nspace, const gchar **class_name)
+{
+ /* mono_get_method_from_token () */
+ g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD);
+ guint32 type_token = mono_metadata_typedef_from_method (image, method_token);
+ if (!type_token) {
+ /* Bad method token (could not find corresponding typedef) */
+ return FALSE;
+ }
+ type_token |= MONO_TOKEN_TYPE_DEF;
+ {
+ /* mono_class_create_from_typedef () */
+ MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
+ guint32 cols [MONO_TYPEDEF_SIZE];
+ guint tidx = mono_metadata_token_index (type_token);
+
+ if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
+ /* "Invalid typedef token %x", type_token */
+ return FALSE;
+ }
+
+ mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
+
+ if (class_name)
+ *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
+ if (nspace)
+ *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
+ return TRUE;
+ }
+}
+
+
+/**
+ * custom_attr_class_name_from_method_token:
+ * @image: The MonoImage
+ * @method_token: a token for a custom attr constructor in @image
+ * @assembly_token: out argment set to the assembly ref token of the custom attr
+ * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
+ * @class_name: out argument set to the class name of the custom attr.
+ *
+ * Given an @image and a @method_token (which is assumed to be a
+ * constructor), fills in the out arguments with the assembly ref (if
+ * a methodref) and the namespace and class name of the custom
+ * attribute.
+ *
+ * Returns: TRUE on success, FALSE otherwise.
+ *
+ * LOCKING: does not take locks
+ */
+static gboolean
+custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token, guint32 *assembly_token, const gchar **nspace, const gchar **class_name)
+{
+ /* This only works with method tokens constructed from a
+ * custom attr token, which can only be methoddef or
+ * memberref */
+ g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD
+ || mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF);
+
+ if (mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF) {
+ /* method_from_memberref () */
+ guint32 cols[6];
+ guint32 nindex, class_index;
+
+ int idx = mono_metadata_token_index (method_token);
+
+ mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3);
+ nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS;
+ class_index = cols [MONO_MEMBERREF_CLASS] & MONO_MEMBERREF_PARENT_MASK;
+ if (class_index == MONO_MEMBERREF_PARENT_TYPEREF) {
+ guint32 type_token = MONO_TOKEN_TYPE_REF | nindex;
+ /* mono_class_from_typeref_checked () */
+ {
+ guint32 cols [MONO_TYPEREF_SIZE];
+ MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
+
+ mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
+
+ if (class_name)
+ *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
+ if (nspace)
+ *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
+ if (assembly_token)
+ *assembly_token = cols [MONO_TYPEREF_SCOPE];
+ return TRUE;
+ }
+ } else if (class_index == MONO_MEMBERREF_PARENT_METHODDEF) {
+ guint32 methoddef_token = MONO_TOKEN_METHOD_DEF | nindex;
+ if (assembly_token)
+ *assembly_token = 0;
+ return custom_attr_class_name_from_methoddef (image, methoddef_token, nspace, class_name);
+ } else {
+ /* Attributes can't be generic, so it won't be
+ * a typespec, and they're always
+ * constructors, so it won't be a moduleref */
+ g_assert_not_reached ();
+ }
+ } else {
+ /* must be MONO_TABLE_METHOD */
+ if (assembly_token)
+ *assembly_token = 0;
+ return custom_attr_class_name_from_methoddef (image, method_token, nspace, class_name);
+ }
+}
+
+/**
+ * mono_assembly_metadata_foreach_custom_attr:
+ * @assembly: the assembly to iterate over
+ * @func: the function to call for each custom attribute
+ * @user_data: passed to @func
+ *
+ * Calls @func for each custom attribute type on the given assembly until @func returns TRUE.
+ * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
+ *
+ */
+void
+mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data)
+{
+ MonoImage *image;
+ guint32 mtoken, i;
+ guint32 cols [MONO_CUSTOM_ATTR_SIZE];
+ MonoTableInfo *ca;
+ guint32 idx;
+
+ /*
+ * This might be called during assembly loading, so do everything using the low-level
+ * metadata APIs.
+ */
+
+ image = assembly->image;
+ g_assert (!image_is_dynamic (image));
+ idx = 1; /* there is only one assembly */
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
+
+ /* Inlined from mono_custom_attrs_from_index_checked () */
+ ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+ i = mono_metadata_custom_attrs_from_index (image, idx);
+ if (!i)
+ return;
+ i --;
+ gboolean stop_iterating = FALSE;
+ while (!stop_iterating && i < ca->rows) {
+ if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
+ break;
+ mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
+ i ++;
+ mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
+ switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
+ case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
+ mtoken |= MONO_TOKEN_METHOD_DEF;
+ break;
+ case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
+ mtoken |= MONO_TOKEN_MEMBER_REF;
+ break;
+ default:
+ g_warning ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
+ continue;
+ }
+
+ const char *nspace = NULL;
+ const char *name = NULL;
+ guint32 assembly_token = 0;
+
+ if (!custom_attr_class_name_from_method_token (image, mtoken, &assembly_token, &nspace, &name))
+ continue;
+
+ stop_iterating = func (image, assembly_token, nspace, name, mtoken, user_data);
+ }
+}
#include <mono/metadata/w32mutex.h>
#include <mono/metadata/w32semaphore.h>
#include <mono/metadata/w32event.h>
+#include <mono/metadata/w32process.h>
#include <metadata/threads.h>
#include <metadata/profiler-private.h>
#include <mono/metadata/coree.h>
static MonoDomain *domain = NULL;
MonoAssembly *ass = NULL;
MonoImageOpenStatus status = MONO_IMAGE_OK;
- const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
+ const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1] = { NULL };
int n, dummy;
#ifdef DEBUG_DOMAIN_UNLOAD
mono_w32mutex_init ();
mono_w32semaphore_init ();
mono_w32event_init ();
+ mono_w32process_init ();
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters_init ();
mono_profiler_appdomain_name (domain, domain->friendly_name);
- /* Have to do this quite late so that we at least have System.Object */
- MonoError custom_attr_error;
- if (mono_assembly_has_reference_assembly_attribute (ass, &custom_attr_error)) {
- char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
- g_print ("Could not load file or assembly %s. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context.", corlib_file);
- g_free (corlib_file);
- exit (1);
- }
- mono_error_assert_ok (&custom_attr_error);
-
return domain;
}
mono_native_tls_free (appdomain_thread_id);
mono_coop_mutex_destroy (&appdomains_mutex);
+ mono_w32process_cleanup ();
+
#ifndef HOST_WIN32
wapi_cleanup ();
#endif
#include <mono/metadata/marshal.h>
#include <mono/utils/strenc.h>
#include <utils/mono-io-portability.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
#undef DEBUG
COULD_NOT_OPEN,
CAPACITY_MUST_BE_POSITIVE,
INVALID_FILE_MODE,
- COULD_NOT_MAP_MEMORY
+ COULD_NOT_MAP_MEMORY,
+ ACCESS_DENIED,
+ CAPACITY_LARGER_THAN_LOGICAL_ADDRESS_SPACE
};
enum {
open_memory_map (const char *c_mapName, int mode, gint64 *capacity, int access, int options, int *ioerror)
{
MmapHandle *handle;
- if (*capacity <= 1) {
+ if (*capacity <= 0) {
*ioerror = CAPACITY_MUST_BE_POSITIVE;
return NULL;
}
+#if SIZEOF_VOID_P == 4
+ if (*capacity > UINT32_MAX) {
+ *ioerror = CAPACITY_LARGER_THAN_LOGICAL_ADDRESS_SPACE;
+ return NULL;
+ }
+#endif
if (!(mode == FILE_MODE_CREATE_NEW || mode == FILE_MODE_OPEN_OR_CREATE || mode == FILE_MODE_OPEN)) {
*ioerror = INVALID_FILE_MODE;
struct stat buf = { 0 };
fstat (fh->fd, &buf); //FIXME error handling
+ *mmap_handle = NULL;
+ *base_address = NULL;
+
if (offset > buf.st_size || ((eff_size + offset) > buf.st_size && !is_special_zero_size_file (&buf)))
- goto error;
+ return ACCESS_DENIED;
/**
* We use the file size if one of the following conditions is true:
* -input size is zero
return 0;
}
-error:
- *mmap_handle = NULL;
- *base_address = NULL;
return COULD_NOT_MAP_MEMORY;
}
/*
- * file-mmap-posix.c: File mmap internal calls
+ * file-mmap-windows.c: MemoryMappedFile internal calls for Windows
*
- * Author:
- * Rodrigo Kumpera
- *
- * Copyright 2014 Xamarin Inc (http://www.xamarin.com)
+ * Copyright 2016 Microsoft
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
+/*
+ * The code in this file has been inspired by the CoreFX MemoryMappedFile Windows implementation contained in the files
+ *
+ * https://github.com/dotnet/corefx/blob/master/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
+ * https://github.com/dotnet/corefx/blob/master/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs
+ */
+
#include <config.h>
#ifdef HOST_WIN32
#include <glib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <mono/metadata/object.h>
#include <mono/metadata/file-mmap.h>
-void *
-mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *error)
+// These control the retry behaviour when lock violation errors occur during Flush:
+#define MAX_FLUSH_WAITS 15 // must be <=30
+#define MAX_FLUSH_RETIRES_PER_WAIT 20
+
+typedef struct {
+ void *address;
+ size_t length;
+} MmapInstance;
+
+enum {
+ BAD_CAPACITY_FOR_FILE_BACKED = 1,
+ CAPACITY_SMALLER_THAN_FILE_SIZE,
+ FILE_NOT_FOUND,
+ FILE_ALREADY_EXISTS,
+ PATH_TOO_LONG,
+ COULD_NOT_OPEN,
+ CAPACITY_MUST_BE_POSITIVE,
+ INVALID_FILE_MODE,
+ COULD_NOT_MAP_MEMORY,
+ ACCESS_DENIED,
+ CAPACITY_LARGER_THAN_LOGICAL_ADDRESS_SPACE
+};
+
+enum {
+ FILE_MODE_CREATE_NEW = 1,
+ FILE_MODE_CREATE = 2,
+ FILE_MODE_OPEN = 3,
+ FILE_MODE_OPEN_OR_CREATE = 4,
+ FILE_MODE_TRUNCATE = 5,
+ FILE_MODE_APPEND = 6,
+};
+
+enum {
+ MMAP_FILE_ACCESS_READ_WRITE = 0,
+ MMAP_FILE_ACCESS_READ = 1,
+ MMAP_FILE_ACCESS_WRITE = 2,
+ MMAP_FILE_ACCESS_COPY_ON_WRITE = 3,
+ MMAP_FILE_ACCESS_READ_EXECUTE = 4,
+ MMAP_FILE_ACCESS_READ_WRITE_EXECUTE = 5,
+};
+
+static DWORD get_page_access (int access)
{
- g_error ("No windows backend");
- return NULL;
+ switch (access) {
+ case MMAP_FILE_ACCESS_READ:
+ return PAGE_READONLY;
+ case MMAP_FILE_ACCESS_READ_WRITE:
+ return PAGE_READWRITE;
+ case MMAP_FILE_ACCESS_COPY_ON_WRITE:
+ return PAGE_WRITECOPY;
+ case MMAP_FILE_ACCESS_READ_EXECUTE:
+ return PAGE_EXECUTE_READ;
+ case MMAP_FILE_ACCESS_READ_WRITE_EXECUTE:
+ return PAGE_EXECUTE_READWRITE;
+ default:
+ g_error ("unknown MemoryMappedFileAccess %d", access);
+ }
}
-void *
-mono_mmap_open_handle (void *handle, MonoString *mapName, gint64 *capacity, int access, int options, int *error)
+static DWORD get_file_access (int access)
{
- g_error ("No windows backend");
- return NULL;
+ switch (access) {
+ case MMAP_FILE_ACCESS_READ:
+ case MMAP_FILE_ACCESS_READ_EXECUTE:
+ return GENERIC_READ;
+ case MMAP_FILE_ACCESS_READ_WRITE:
+ case MMAP_FILE_ACCESS_COPY_ON_WRITE:
+ case MMAP_FILE_ACCESS_READ_WRITE_EXECUTE:
+ return GENERIC_READ | GENERIC_WRITE;
+ case MMAP_FILE_ACCESS_WRITE:
+ return GENERIC_WRITE;
+ default:
+ g_error ("unknown MemoryMappedFileAccess %d", access);
+ }
}
-void
-mono_mmap_close (void *mmap_handle)
+static int get_file_map_access (int access)
{
- g_error ("No windows backend");
+ switch (access) {
+ case MMAP_FILE_ACCESS_READ:
+ return FILE_MAP_READ;
+ case MMAP_FILE_ACCESS_WRITE:
+ return FILE_MAP_WRITE;
+ case MMAP_FILE_ACCESS_READ_WRITE:
+ return FILE_MAP_READ | FILE_MAP_WRITE;
+ case MMAP_FILE_ACCESS_COPY_ON_WRITE:
+ return FILE_MAP_COPY;
+ case MMAP_FILE_ACCESS_READ_EXECUTE:
+ return FILE_MAP_EXECUTE | FILE_MAP_READ;
+ case MMAP_FILE_ACCESS_READ_WRITE_EXECUTE:
+ return FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE;
+ default:
+ g_error ("unknown MemoryMappedFileAccess %d", access);
+ }
}
-void
-mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability)
+static int convert_win32_error (int error, int def)
{
- g_error ("No windows backend");
+ switch (error) {
+ case ERROR_FILE_NOT_FOUND:
+ return FILE_NOT_FOUND;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ return FILE_ALREADY_EXISTS;
+ case ERROR_ACCESS_DENIED:
+ return ACCESS_DENIED;
+ }
+ return def;
}
-void
-mono_mmap_flush (void *mmap_handle)
+static void *open_handle (void *handle, MonoString *mapName, int mode, gint64 *capacity, int access, int options, int *error)
{
- g_error ("No windows backend");
+ g_assert (handle != NULL);
+
+ wchar_t *w_mapName = NULL;
+ HANDLE result = NULL;
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ if (*capacity <= 0) {
+ *error = CAPACITY_MUST_BE_POSITIVE;
+ return NULL;
+ }
+#if SIZEOF_VOID_P == 4
+ if (*capacity > UINT32_MAX) {
+ *error = CAPACITY_LARGER_THAN_LOGICAL_ADDRESS_SPACE;
+ return NULL;
+ }
+#endif
+ if (!(mode == FILE_MODE_CREATE_NEW || mode == FILE_MODE_OPEN_OR_CREATE || mode == FILE_MODE_OPEN)) {
+ *error = INVALID_FILE_MODE;
+ return NULL;
+ }
+ } else {
+ FILE_STANDARD_INFO info;
+ if (!GetFileInformationByHandleEx ((HANDLE) handle, FileStandardInfo, &info, sizeof (FILE_STANDARD_INFO))) {
+ *error = convert_win32_error (GetLastError (), COULD_NOT_OPEN);
+ return NULL;
+ }
+ if (*capacity == 0) {
+ if (info.EndOfFile.QuadPart == 0) {
+ *error = CAPACITY_SMALLER_THAN_FILE_SIZE;
+ return NULL;
+ }
+ } else if (*capacity < info.EndOfFile.QuadPart) {
+ *error = CAPACITY_SMALLER_THAN_FILE_SIZE;
+ return NULL;
+ }
+ }
+
+ w_mapName = mapName ? mono_string_to_utf16 (mapName) : NULL;
+
+ if (mode == FILE_MODE_CREATE_NEW || handle != INVALID_HANDLE_VALUE) {
+ result = CreateFileMappingW ((HANDLE)handle, NULL, get_page_access (access) | options, (DWORD)(((guint64)*capacity) >> 32), (DWORD)*capacity, w_mapName);
+ if (result && GetLastError () == ERROR_ALREADY_EXISTS) {
+ CloseHandle (result);
+ result = NULL;
+ *error = FILE_ALREADY_EXISTS;
+ } else if (!result && GetLastError () != NO_ERROR) {
+ *error = convert_win32_error (GetLastError (), COULD_NOT_OPEN);
+ }
+ } else if (mode == FILE_MODE_OPEN || mode == FILE_MODE_OPEN_OR_CREATE && access == MMAP_FILE_ACCESS_WRITE) {
+ result = OpenFileMappingW (get_file_map_access (access), FALSE, w_mapName);
+ if (!result) {
+ if (mode == FILE_MODE_OPEN_OR_CREATE && GetLastError () == ERROR_FILE_NOT_FOUND) {
+ *error = INVALID_FILE_MODE;
+ } else {
+ *error = convert_win32_error (GetLastError (), COULD_NOT_OPEN);
+ }
+ }
+ } else if (mode == FILE_MODE_OPEN_OR_CREATE) {
+
+ // This replicates how CoreFX does MemoryMappedFile.CreateOrOpen ().
+
+ /// Try to open the file if it exists -- this requires a bit more work. Loop until we can
+ /// either create or open a memory mapped file up to a timeout. CreateFileMapping may fail
+ /// if the file exists and we have non-null security attributes, in which case we need to
+ /// use OpenFileMapping. But, there exists a race condition because the memory mapped file
+ /// may have closed between the two calls -- hence the loop.
+ ///
+ /// The retry/timeout logic increases the wait time each pass through the loop and times
+ /// out in approximately 1.4 minutes. If after retrying, a MMF handle still hasn't been opened,
+ /// throw an InvalidOperationException.
+
+ guint32 waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins
+ guint32 waitSleep = 0;
+
+ while (waitRetries > 0) {
+ result = CreateFileMappingW ((HANDLE)handle, NULL, get_page_access (access) | options, (DWORD)(((guint64)*capacity) >> 32), (DWORD)*capacity, w_mapName);
+ if (result)
+ break;
+ if (GetLastError() != ERROR_ACCESS_DENIED) {
+ *error = convert_win32_error (GetLastError (), COULD_NOT_OPEN);
+ break;
+ }
+ result = OpenFileMappingW (get_file_map_access (access), FALSE, w_mapName);
+ if (result)
+ break;
+ if (GetLastError () != ERROR_FILE_NOT_FOUND) {
+ *error = convert_win32_error (GetLastError (), COULD_NOT_OPEN);
+ break;
+ }
+ // increase wait time
+ --waitRetries;
+ if (waitSleep == 0) {
+ waitSleep = 10;
+ } else {
+ mono_thread_info_sleep (waitSleep, NULL);
+ waitSleep *= 2;
+ }
+ }
+
+ if (!result) {
+ *error = COULD_NOT_OPEN;
+ }
+ }
+
+ if (w_mapName)
+ g_free (w_mapName);
+ return result;
}
+void *mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *error)
+{
+ g_assert (path != NULL || mapName != NULL);
+
+ wchar_t *w_path = NULL;
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ HANDLE result = NULL;
+ gboolean delete_on_error = FALSE;
+ if (path) {
+ w_path = mono_string_to_utf16 (path);
+ WIN32_FILE_ATTRIBUTE_DATA file_attrs;
+ gboolean existed = GetFileAttributesExW (w_path, GetFileExInfoStandard, &file_attrs);
+ if (!existed && mode == FILE_MODE_CREATE_NEW && *capacity == 0) {
+ *error = CAPACITY_SMALLER_THAN_FILE_SIZE;
+ goto done;
+ }
+ hFile = CreateFileW (w_path, get_file_access (access), FILE_SHARE_READ, NULL, mode, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ *error = convert_win32_error (GetLastError (), COULD_NOT_OPEN);
+ goto done;
+ }
+ delete_on_error = !existed;
+ }
-int
-mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address)
+ result = open_handle (hFile, mapName, mode, capacity, access, options, error);
+
+done:
+ if (!result && delete_on_error)
+ DeleteFileW (w_path);
+ if (w_path)
+ g_free (w_path);
+
+ return result;
+}
+
+void *mono_mmap_open_handle (void *handle, MonoString *mapName, gint64 *capacity, int access, int options, int *error)
{
- g_error ("No windows backend");
+ g_assert (handle != NULL);
+
+ return open_handle (handle, mapName, FILE_MODE_OPEN, capacity, access, options, error);
+}
+
+void mono_mmap_close (void *mmap_handle)
+{
+ g_assert (mmap_handle);
+ CloseHandle ((HANDLE) mmap_handle);
+}
+
+void mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability)
+{
+ g_assert (mmap_handle);
+ if (!SetHandleInformation ((HANDLE) mmap_handle, HANDLE_FLAG_INHERIT, inheritability ? HANDLE_FLAG_INHERIT : 0)) {
+ g_error ("mono_mmap_configure_inheritability: SetHandleInformation failed with error %d!", GetLastError ());
+ }
+}
+
+void mono_mmap_flush (void *mmap_handle)
+{
+ g_assert (mmap_handle);
+ MmapInstance *h = (MmapInstance *)mmap_handle;
+
+ if (FlushViewOfFile (h->address, h->length))
+ return;
+
+ // This replicates how CoreFX does MemoryMappedView.Flush ().
+
+ // It is a known issue within the NTFS transaction log system that
+ // causes FlushViewOfFile to intermittently fail with ERROR_LOCK_VIOLATION
+ // As a workaround, we catch this particular error and retry the flush operation
+ // a few milliseconds later. If it does not work, we give it a few more tries with
+ // increasing intervals. Eventually, however, we need to give up. In ad-hoc tests
+ // this strategy successfully flushed the view after no more than 3 retries.
+
+ if (GetLastError () != ERROR_LOCK_VIOLATION)
+ // TODO: Propagate error to caller
+ return;
+
+ for (int w = 0; w < MAX_FLUSH_WAITS; w++) {
+ int pause = (1 << w); // MaxFlushRetries should never be over 30
+ mono_thread_info_sleep (pause, NULL);
+
+ for (int r = 0; r < MAX_FLUSH_RETIRES_PER_WAIT; r++) {
+ if (FlushViewOfFile (h->address, h->length))
+ return;
+
+ if (GetLastError () != ERROR_LOCK_VIOLATION)
+ // TODO: Propagate error to caller
+ return;
+
+ mono_thread_info_yield ();
+ }
+ }
+
+ // We got to here, so there was no success:
+ // TODO: Propagate error to caller
+}
+
+int mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address)
+{
+ static DWORD allocationGranularity = 0;
+ if (allocationGranularity == 0) {
+ SYSTEM_INFO info;
+ GetSystemInfo (&info);
+ allocationGranularity = info.dwAllocationGranularity;
+ }
+
+ gint64 extraMemNeeded = offset % allocationGranularity;
+ guint64 newOffset = offset - extraMemNeeded;
+ gint64 nativeSize = (*size != 0) ? *size + extraMemNeeded : 0;
+
+#if SIZEOF_VOID_P == 4
+ if (nativeSize > UINT32_MAX)
+ return CAPACITY_LARGER_THAN_LOGICAL_ADDRESS_SPACE;
+#endif
+
+ void *address = MapViewOfFile ((HANDLE) handle, get_file_map_access (access), (DWORD) (newOffset >> 32), (DWORD) newOffset, (SIZE_T) nativeSize);
+ if (!address)
+ return convert_win32_error (GetLastError (), COULD_NOT_MAP_MEMORY);
+
+ // Query the view for its size and allocation type
+ MEMORY_BASIC_INFORMATION viewInfo;
+ VirtualQuery (address, &viewInfo, sizeof (MEMORY_BASIC_INFORMATION));
+ guint64 viewSize = (guint64) viewInfo.RegionSize;
+
+ // Allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option
+ // OR check if the allocated view size is smaller than the expected native size
+ // If multiple overlapping views are created over the file mapping object, the pages in a given region
+ // could have different attributes(MEM_RESERVE OR MEM_COMMIT) as MapViewOfFile preserves coherence between
+ // views created on a mapping object backed by same file.
+ // In which case, the viewSize will be smaller than nativeSize required and viewState could be MEM_COMMIT
+ // but more pages may need to be committed in the region.
+ // This is because, VirtualQuery function(that internally invokes VirtualQueryEx function) returns the attributes
+ // and size of the region of pages with matching attributes starting from base address.
+ // VirtualQueryEx: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366907(v=vs.85).aspx
+ if (((viewInfo.State & MEM_RESERVE) != 0) || viewSize < (guint64) nativeSize) {
+ void *tempAddress = VirtualAlloc (address, nativeSize != 0 ? nativeSize : viewSize, MEM_COMMIT, get_page_access (access));
+ if (!tempAddress) {
+ return convert_win32_error (GetLastError (), COULD_NOT_MAP_MEMORY);
+ }
+ // again query the view for its new size
+ VirtualQuery (address, &viewInfo, sizeof (MEMORY_BASIC_INFORMATION));
+ viewSize = (guint64) viewInfo.RegionSize;
+ }
+
+ if (*size == 0)
+ *size = viewSize - extraMemNeeded;
+
+ MmapInstance *h = g_malloc0 (sizeof (MmapInstance));
+ h->address = address;
+ h->length = *size + extraMemNeeded;
+ *mmap_handle = h;
+ *base_address = (char*) address + (offset - newOffset);
+
return 0;
}
-gboolean
-mono_mmap_unmap (void *mmap_handle)
+gboolean mono_mmap_unmap (void *mmap_handle)
{
- g_error ("No windows backend");
- return TRUE;
+ g_assert (mmap_handle);
+
+ MmapInstance *h = (MmapInstance *) mmap_handle;
+
+ gboolean result = UnmapViewOfFile (h->address);
+
+ g_free (h);
+ return result;
}
#endif
void mono_gc_register_altstack (gpointer stack, gint32 stack_size, gpointer altstack, gint32 altstack_size);
+gboolean mono_gc_is_critical_method (MonoMethod *method);
+
/* If set, print debugging messages around finalizers. */
extern gboolean log_finalizers;
static void reference_queue_clear_for_domain (MonoDomain *domain);
-static guint32
-guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
+static MonoThreadInfoWaitRet
+guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable)
{
- guint32 result;
+ MonoThreadInfoWaitRet result;
MONO_ENTER_GC_SAFE;
- result = WaitForSingleObjectEx (handle, timeout, alertable);
+ result = mono_thread_info_wait_one_handle (thread_handle, timeout, alertable);
MONO_EXIT_GC_SAFE;
return result;
ResetEvent (pending_done_event);
mono_gc_finalize_notify ();
/* g_print ("Waiting for pending finalizers....\n"); */
- guarded_wait (pending_done_event, INFINITE, TRUE);
+ MONO_ENTER_GC_SAFE;
+ WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE);
+ MONO_EXIT_GC_SAFE;
/* g_print ("Done pending....\n"); */
#else
gboolean alerted = FALSE;
} else {
/* the C# code will check and throw the exception */
/* FIXME: missing !klass->blittable test, see bug #61134 */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if (mono_class_is_auto_layout (klass))
return (gpointer)-1;
return (char*)obj + sizeof (MonoObject);
}
if (!gc_disabled) {
finished = TRUE;
if (mono_thread_internal_current () != gc_thread) {
+ int ret;
gint64 start_ticks = mono_msec_ticks ();
gint64 end_ticks = start_ticks + 2000;
}
if (!finalizer_thread_exited) {
- int ret;
-
/* Set a flag which the finalizer thread can check */
suspend_finalizers = TRUE;
mono_gc_suspend_finalizers ();
/* Wait for it to stop */
ret = guarded_wait (gc_thread->handle, 100, TRUE);
- if (ret == WAIT_TIMEOUT) {
+ if (ret == MONO_THREAD_INFO_WAIT_RET_TIMEOUT) {
/*
* The finalizer thread refused to exit. Make it stop.
*/
mono_thread_internal_stop (gc_thread);
ret = guarded_wait (gc_thread->handle, 100, TRUE);
- g_assert (ret != WAIT_TIMEOUT);
+ g_assert (ret != MONO_THREAD_INFO_WAIT_RET_TIMEOUT);
/* The thread can't set this flag */
finalizer_thread_exited = TRUE;
}
}
- int ret;
/* Wait for the thread to actually exit */
ret = guarded_wait (gc_thread->handle, INFINITE, TRUE);
- g_assert (ret == WAIT_OBJECT_0);
+ g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0);
mono_thread_join (GUINT_TO_POINTER (gc_thread->tid));
g_assert (finalizer_thread_exited);
while (cur) {
int i;
- for (i = 0; i < cur->size; ++i)
- func ((gpointer*)&cur->objects [i], gc_data);
+ for (i = 0; i < cur->size; ++i) {
+ if (cur->objects [i] != NULL)
+ func ((gpointer*)&cur->objects [i], gc_data);
+ }
if (cur == last)
break;
cur = cur->next;
}
if (size > THIS_IS_AN_OK_NUMBER_OF_HANDLES)
- printf ("%s USED %d handles\n", func_name, size);
+ g_warning ("%s USED %d handles\n", func_name, size);
}
/*
ICALL(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll)
ICALL(MARSHAL_15, "PtrToStringAnsi(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi)
ICALL(MARSHAL_16, "PtrToStringAnsi(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len)
-#ifndef DISABLE_COM
ICALL(MARSHAL_17, "PtrToStringBSTR", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR)
-#endif
ICALL(MARSHAL_18, "PtrToStringUni(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni)
ICALL(MARSHAL_19, "PtrToStringUni(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len)
ICALL(MARSHAL_20, "PtrToStructure(intptr,System.Type)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type)
void
mono_icall_write_windows_debug_string (MonoString *message);
-MonoBoolean
-mono_icall_close_process (gpointer handle);
-
gint32
mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds);
#endif /* HOST_WIN32 */
guint32
mono_icall_drive_info_get_drive_type (MonoString *root_path_name);
-
-MonoBoolean
-mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max);
-
-MonoBoolean
-mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max);
-
-gint32
-mono_icall_get_priority_class (gpointer handle);
-
-MonoBoolean
-mono_icall_set_priority_class (gpointer handle, gint32 priorityClass);
#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
#endif /* __MONO_METADATA_ICALL_INTERNALS_H__ */
return WAIT_TIMEOUT;
}
-MonoBoolean
-mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("GetProcessWorkingSetSize");
-
- mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "GetProcessWorkingSetSize");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-MonoBoolean
-mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("SetProcessWorkingSetSize");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "SetProcessWorkingSetSize");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-gint32
-mono_icall_get_priority_class (gpointer handle)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("GetPriorityClass");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetPriorityClass");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-MonoBoolean
-mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("SetPriorityClass");
-
- mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "SetPriorityClass");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
#ifdef _MSC_VER
OutputDebugString (mono_string_chars (message));
}
-MonoBoolean
-mono_icall_close_process (gpointer handle)
-{
- return (MonoBoolean)(CloseHandle (handle));
-}
#endif /* HOST_WIN32 */
#include <mono/metadata/sysmath.h>
#include <mono/metadata/string-icalls.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/process.h>
+#include <mono/metadata/w32process.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/locales.h>
klass = mono_class_from_mono_type (handle);
MONO_CHECK_ARG (handle, klass,);
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
return;
vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
}
static MonoReflectionType *
-type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
+type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
{
MonoMethod *m, *dest;
} else {
g_warning (G_STRLOC);
}
+ *caller_assembly = assembly;
if (info->assembly.name)
assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
MonoTypeNameParse info;
MonoReflectionType *type = NULL;
gboolean parsedOk;
+ MonoAssembly *caller_assembly;
char *str = mono_string_to_utf8_checked (name, &error);
if (!is_ok (&error))
goto leave;
}
- type = type_from_parsed_name (&info, ignoreCase, &error);
+ type = type_from_parsed_name (&info, ignoreCase, &caller_assembly, &error);
- mono_reflection_free_type_info (&info);
-
- if (!is_ok (&error))
+ if (!is_ok (&error)) {
+ mono_reflection_free_type_info (&info);
goto leave;
+ }
- if (type == NULL){
+ if (type == NULL) {
if (throwOnError) {
- mono_error_set_type_load_name (&error, g_strdup (str), g_strdup (""), "");
- goto leave;
+ char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
+ char *aname;
+ if (info.assembly.name)
+ aname = mono_stringify_assembly_name (&info.assembly);
+ else if (caller_assembly)
+ aname = mono_stringify_assembly_name (mono_assembly_get_name (caller_assembly));
+ else
+ aname = g_strdup ("");
+ mono_error_set_type_load_name (&error, tname, aname, "");
}
+ mono_reflection_free_type_info (&info);
+ goto leave;
}
leave:
ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
{
MonoClass *klass = mono_class_from_mono_type (type->type);
- return klass->flags;
+ return mono_class_get_flags (klass);
}
ICALL_EXPORT MonoReflectionMarshalAsAttribute*
MonoType *ftype;
int i;
- if (klass->generic_container ||
- (klass->generic_class && klass->generic_class->context.class_inst->is_open))
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (mono_class_is_gtd (klass) ||
+ (gklass && gklass->context.class_inst->is_open))
return NULL;
ftype = mono_field_get_type (field->field);
ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
{
MonoClass *parent = field->field->parent;
- if (!parent->size_inited)
- mono_class_init (parent);
mono_class_setup_fields (parent);
return field->field->offset - sizeof (MonoObject);
if (!mono_error_ok (data->error))
return;
- if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
+ if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
if (!mono_error_ok (data->error))
return;
GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
- if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
+ if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
data.context = mono_class_get_context (klass);
- klass = klass->generic_class->container_class;
+ klass = mono_class_get_generic_class (klass)->container_class;
}
for (parent = klass; parent; parent = parent->parent) {
klass = mono_class_from_mono_type (type->type);
- if (klass->generic_container) {
- MonoGenericContainer *container = klass->generic_container;
+ if (mono_class_is_gtd (klass)) {
+ MonoGenericContainer *container = mono_class_get_generic_container (klass);
res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
if (mono_error_set_pending_exception (&error))
return NULL;
mono_array_setref (res, i, rt);
}
- } else if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ } else if (mono_class_is_ginst (klass)) {
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
if (mono_error_set_pending_exception (&error))
return NULL;
return FALSE;
klass = mono_class_from_mono_type (type->type);
- return klass->generic_container != NULL;
+ return mono_class_is_gtd (klass);
}
ICALL_EXPORT MonoReflectionType*
klass = mono_class_from_mono_type (type->type);
- if (klass->generic_container) {
+ if (mono_class_is_gtd (klass)) {
return type; /* check this one */
}
- if (klass->generic_class) {
- MonoClass *generic_class = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
gpointer tb;
tb = mono_class_get_ref_info (generic_class);
klass = mono_class_from_mono_type (geninst);
/*we might inflate to the GTD*/
- if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
+ if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
return NULL;
}
return FALSE;
klass = mono_class_from_mono_type (type->type);
- return klass->generic_class != NULL || klass->generic_container != NULL;
+ return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
}
ICALL_EXPORT gint32
return NULL;
}
- if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
+ if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
return NULL;
}
* nested types that aren't generic. In any case, the container of that
* nested type would be the generic type definition.
*/
- if (klass->generic_class)
- klass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ klass = mono_class_get_generic_class (klass)->container_class;
res_array = g_ptr_array_new ();
iter = NULL;
while ((nested = mono_class_get_nested_types (klass, &iter))) {
match = 0;
- if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
+ if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
if (bflags & BFLAGS_Public)
match++;
} else {
MonoGenericContext ctx;
ctx.method_inst = inflated->context.method_inst;
ctx.class_inst = inflated->context.class_inst;
- if (klass->generic_class)
- ctx.class_inst = klass->generic_class->context.class_inst;
- else if (klass->generic_container)
- ctx.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (klass))
+ ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
+ else if (mono_class_is_gtd (klass))
+ ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
return result;
mono_class_setup_vtable (klass);
vtable = klass->vtable;
- if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (method->klass)) {
gboolean variance_used = FALSE;
/*MS fails with variant interfaces but it's the right thing to do anyway.*/
int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
if (mono_error_set_pending_exception (&error))
return NULL;
- if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
return NULL;
}
return m;
klass = method->klass;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
generic_inst = mono_class_get_context (klass);
- klass = klass->generic_class->container_class;
+ klass = mono_class_get_generic_class (klass)->container_class;
}
retry:
return NULL;
}
}
- if (parent->generic_class) {
+ if (mono_class_is_ginst (parent)) {
parent_inst = mono_class_get_context (parent);
- parent = parent->generic_class->container_class;
+ parent = mono_class_get_generic_class (parent)->container_class;
}
mono_class_setup_vtable (parent);
generic_inst = NULL;
}
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
generic_inst = mono_class_get_context (klass);
- klass = klass->generic_class->container_class;
+ klass = mono_class_get_generic_class (klass)->container_class;
}
}
return message;
}
-ICALL_EXPORT gpointer
-ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
-{
- return GetCurrentProcess ();
-}
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
-{
- return GetExitCodeProcess (handle, (guint32*) exitcode);
-}
-
-#ifndef HOST_WIN32
-static inline MonoBoolean
-mono_icall_close_process (gpointer handle)
-{
- return CloseProcess (handle);
-}
-#endif /* !HOST_WIN32 */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
-{
- return mono_icall_close_process (handle);
-}
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
-{
- return TerminateProcess (handle, exitcode);
-}
-
#ifndef HOST_WIN32
static inline gint32
mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
return mono_icall_wait_for_input_idle (handle, milliseconds);
}
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline MonoBoolean
-mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
-{
- return GetProcessWorkingSetSize (handle, min, max);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
-{
- return mono_icall_get_process_working_set_size (handle, min, max);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline MonoBoolean
-mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
-{
- return SetProcessWorkingSetSize (handle, min, max);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
-{
- return mono_icall_set_process_working_set_size (handle, min, max);
-}
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
-{
- return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
-}
-
ICALL_EXPORT gint32
ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
{
return mono_process_current_pid ();
}
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline gint32
-mono_icall_get_priority_class (gpointer handle)
-{
- return GetPriorityClass (handle);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT gint32
-ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
-{
- return mono_icall_get_priority_class (handle);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline MonoBoolean
-mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
-{
- return SetPriorityClass (handle, priorityClass);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
-{
- return mono_icall_set_priority_class (handle, priorityClass);
-}
-
ICALL_EXPORT MonoBoolean
ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
{
static gpointer*
class_next_value (gpointer value)
{
- MonoClass *klass = (MonoClass *)value;
+ MonoClassDef *klass = (MonoClassDef *)value;
return (gpointer*)&klass->next_class_cache;
}
}
}
- if (field && field->parent && !field->parent->generic_class && !field->parent->generic_container) {
+ if (field && field->parent && !mono_class_is_ginst (field->parent) && !mono_class_is_gtd (field->parent)) {
mono_image_lock (image);
mono_conc_hashtable_insert (image->field_cache, GUINT_TO_POINTER (token), field);
mono_image_unlock (image);
/* Search directly in the metadata to avoid calling setup_methods () */
mono_error_init (error);
- /* FIXME: !from_class->generic_class condition causes test failures. */
- if (klass->type_token && !image_is_dynamic (klass->image) && !klass->methods && !klass->rank && klass == from_class && !from_class->generic_class) {
+ /* FIXME: !mono_class_is_ginst (from_class) condition causes test failures. */
+ if (klass->type_token && !image_is_dynamic (klass->image) && !klass->methods && !klass->rank && klass == from_class && !mono_class_is_ginst (from_class)) {
+ int first_idx = mono_class_get_first_method_idx (klass);
for (i = 0; i < klass->method.count; ++i) {
guint32 cols [MONO_METHOD_SIZE];
MonoMethod *method;
const char *m_name;
MonoMethodSignature *other_sig;
- mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
+ mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
m_name = mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]);
(name && !strcmp (m_name, name))))
continue;
- method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, error);
+ method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, error);
if (!mono_error_ok (error)) //bail out if we hit a loader error
return NULL;
if (method) {
return mono_method_signature_checked (method, error);
}
- if (method->klass->generic_class)
+ if (mono_class_is_ginst (method->klass))
return mono_method_signature_checked (method, error);
if (image_is_dynamic (image)) {
type = &klass->byval_arg;
if (type->type != MONO_TYPE_ARRAY && type->type != MONO_TYPE_SZARRAY) {
- MonoClass *in_class = klass->generic_class ? klass->generic_class->container_class : klass;
+ MonoClass *in_class = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->container_class : klass;
method = find_method (in_class, NULL, mname, sig, klass, error);
break;
}
klass = method->klass;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
g_assert (method->is_inflated);
method = ((MonoMethodInflated *) method)->declaring;
}
- new_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+ new_context.class_inst = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->context.class_inst : NULL;
new_context.method_inst = inst;
method = mono_class_inflate_generic_method_full_checked (method, klass, &new_context, error);
sig = mono_metadata_blob_heap (image, cols [4]);
/* size = */ mono_metadata_decode_blob_size (sig, &sig);
- container = klass->generic_container;
+ container = mono_class_try_get_generic_container (klass);
/*
* load_generic_params does a binary search so only call it if the method
sig = mono_metadata_blob_heap (img, sig_offset = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_SIGNATURE));
- g_assert (!m->klass->generic_class);
+ g_assert (!mono_class_is_ginst (m->klass));
container = mono_method_get_generic_container (m);
if (!container)
- container = m->klass->generic_container;
+ container = mono_class_try_get_generic_container (m->klass);
/* Generic signatures depend on the container so they cannot be cached */
/* icall/pinvoke signatures cannot be cached cause we modify them below */
*/
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass);
return mono_metadata_parse_mh_full (img, container, (const char *)loc, error);
}
mono_class_setup_methods (klass);
if (mono_class_has_failure (klass))
return 0;
+ int first_idx = mono_class_get_first_method_idx (klass);
for (i = 0; i < klass->method.count; ++i) {
if (method == klass->methods [i]) {
if (klass->image->uncompressed_metadata)
- return mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
+ return mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
else
- return klass->method.first + i + 1;
+ return first_idx + i + 1;
}
}
return 0;
mono_marshal_free_hglobal (void *ptr);
gpointer
-mono_string_to_lpstr (MonoString *s);
+mono_string_to_utf8str (MonoString *s);
#endif /* HOST_WIN32 */
#endif /* __MONO_METADATA_MARSHAL_INTERNALS_H__ */
}
gpointer
-mono_string_to_lpstr (MonoString *s)
+mono_string_to_utf8str (MonoString *s)
{
char *as, *tmp;
glong len;
static gboolean use_aot_wrappers;
+static int class_marshal_info_count;
+
static void ftnptr_eh_callback_default (guint32 gchandle);
static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
static void *
mono_marshal_string_to_utf16_copy (MonoString *s);
+#ifndef HOST_WIN32
static gpointer
mono_string_to_utf8str (MonoString *string_obj);
+#endif
static MonoStringBuilder *
mono_string_utf8_to_builder2 (char *text);
mono_cominterop_init ();
mono_remoting_init ();
+
+ mono_counters_register ("MonoClass::class_marshal_info_count count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_marshal_info_count);
+
}
}
return str;
}
+#ifndef HOST_WIN32
/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
static gpointer
mono_string_to_utf8str (MonoString *s)
mono_error_set_pending_exception (&error);
return result;
}
+#endif
gpointer
mono_string_to_ansibstr (MonoString *string_obj)
}
if (klass != mono_class_try_get_safehandle_class ()) {
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (mono_class_is_auto_layout (klass)) {
char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.",
mono_type_full_name (&klass->byval_arg));
mono_mb_emit_exception_marshal_directive (mb, msg);
* the layout to the managed structure as well.
*/
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && (usize == 0)) {
+ if (mono_class_is_explicit_layout (klass) && (usize == 0)) {
if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) ||
((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type))))
g_error ("Type %s which has an [ExplicitLayout] attribute cannot have a "
MonoMethod *res;
GHashTable *cache;
gpointer cache_key = NULL;
- SignaturePointerPair key;
+ SignaturePointerPair key = { NULL, NULL };
SignaturePointerPair *new_key;
int local_i, local_len, local_delegates, local_d, local_target, local_res;
int pos0, pos1, pos2;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
invoke_sig = sig = mono_signature_no_pinvoke (method);
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype)
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
break;
conv_arg = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
/* Have to change the signature since the vtype is passed byref */
m->csig->params [argnum - m->csig->hasthis] = &mono_defaults.int_class->byval_arg;
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype)
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
mono_mb_emit_ldarg_addr (mb, argnum);
else
mono_mb_emit_ldloc (mb, conv_arg);
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
mono_mb_emit_ldarg (mb, argnum);
break;
}
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype)
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
break;
if (t->byref) {
break;
case MARSHAL_ACTION_CONV_RESULT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable) {
mono_mb_emit_stloc (mb, 3);
break;
}
break;
case MARSHAL_ACTION_MANAGED_CONV_IN:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
conv_arg = 0;
break;
}
break;
case MARSHAL_ACTION_MANAGED_CONV_OUT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
break;
- }
-
if (t->byref && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))
break;
break;
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype) {
+ if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
mono_mb_emit_stloc (mb, 3);
m->retobj_var = 0;
break;
MonoMethod *ctor = NULL;
int intptr_handle_slot;
- if (t->data.klass->flags & TYPE_ATTRIBUTE_ABSTRACT){
+ if (mono_class_is_abstract (t->data.klass)) {
mono_mb_emit_byte (mb, CEE_POP);
mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
break;
}
/* The class can not have an automatic layout */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (mono_class_is_auto_layout (klass)) {
mono_mb_emit_auto_layout_exception (mb, klass);
break;
}
}
/* The class can not have an automatic layout */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (mono_class_is_auto_layout (klass)) {
mono_mb_emit_auto_layout_exception (mb, klass);
break;
}
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
MonoClass *klass = mono_class_from_mono_type (sig->ret);
mono_class_init (klass);
- if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+ if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
/* This is used by emit_marshal_vtype (), but it needs to go right before the call */
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
MonoClass *klass = mono_class_from_mono_type (sig->ret);
mono_class_init (klass);
- if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+ if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
/* This is used by emit_marshal_vtype (), but it needs to go right before the call */
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
method = ((MonoMethodInflated*)method)->declaring;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
}
method = ((MonoMethodInflated*)method)->declaring;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
}
return FALSE;
element_class = klass->element_class;
- return (element_class->flags & TYPE_ATTRIBUTE_SEALED) || element_class->valuetype;
+ return mono_class_is_sealed (element_class) || element_class->valuetype;
}
static int
/*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/
if (mono_class_is_marshalbyref (element_class) || element_class->rank || mono_class_has_variant_generic_params (element_class))
return STELEMREF_COMPLEX;
- if (element_class->flags & TYPE_ATTRIBUTE_SEALED)
+ if (mono_class_is_sealed (element_class))
return STELEMREF_SEALED_CLASS;
return STELEMREF_CLASS;
}
/* uiid = klass->interface_id; */
mono_mb_emit_ldloc (mb, aklass);
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoClass, interface_id));
- mono_mb_emit_byte (mb, CEE_LDIND_U2);
+ mono_mb_emit_byte (mb, CEE_LDIND_U4);
mono_mb_emit_stloc (mb, uiid);
/*if (uiid > vt->max_interface_id)*/
mono_mb_emit_ldloc (mb, uiid);
mono_mb_emit_ldloc (mb, vtable);
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id));
- mono_mb_emit_byte (mb, CEE_LDIND_U2);
+ mono_mb_emit_byte (mb, CEE_LDIND_U4);
b2 = mono_mb_emit_branch (mb, CEE_BGT_UN);
/* if (!(vt->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7)))) */
return 0;
}
- layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
+ layout = (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK);
if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
return sizeof (gpointer);
count++;
}
- layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+ layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
/* The mempool is protected by the loader lock */
info = (MonoMarshalType *)mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
/*We do double-checking locking on marshal_info */
mono_memory_barrier ();
klass->marshal_info = info;
+ ++class_marshal_info_count;
}
mono_marshal_unlock ();
klass = t->data.klass;
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if (mono_class_is_auto_layout (klass))
break;
- if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype))
+ if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
return mono_object_unbox (o);
res = mono_marshal_alloc (mono_class_native_size (klass, NULL), &error);
case MONO_TYPE_VALUETYPE: {
klass = t->data.klass;
- if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
- klass->blittable || klass->enumtype))
+ if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
break;
if (param_attrs & PARAM_ATTRIBUTE_OUT) {
static gboolean
mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
{
- MonoGenericContainer *container = container_class->generic_container;
+ MonoGenericContainer *container = mono_class_get_generic_container (container_class);
if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
return FALSE;
MonoImageSet *set;
CollectData data;
+ g_assert (mono_class_get_generic_container (container_class)->type_argc == inst->type_argc);
+
memset (&helper, 0, sizeof(helper)); // act like g_new0
helper.container_class = container_class;
helper.context.class_inst = inst;
gclass->context.class_inst = inst;
gclass->context.method_inst = NULL;
gclass->owner = set;
- if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
+ if (inst == mono_class_get_generic_container (container_class)->context.class_inst && !is_tb_open)
gclass->cached_class = container_class;
g_hash_table_insert (set->gclass_cache, gclass, gclass);
return FALSE;
gklass = mono_class_from_mono_type (gtype);
- if (!gklass->generic_container) {
+ if (!mono_class_is_gtd (gklass)) {
mono_error_set_bad_image (error, m, "Generic instance with non-generic definition");
return FALSE;
}
_mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
{
MonoGenericInst *i1 = g1->context.class_inst;
- MonoGenericInst *i2 = c2->generic_container->context.class_inst;
+ MonoGenericInst *i2 = mono_class_get_generic_container (c2)->context.class_inst;
if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
return FALSE;
{
if (c1 == c2)
return TRUE;
- if (c1->generic_class && c2->generic_class)
- return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
- if (c1->generic_class && c2->generic_container)
- return _mono_metadata_generic_class_container_equal (c1->generic_class, c2, signature_only);
- if (c1->generic_container && c2->generic_class)
- return _mono_metadata_generic_class_container_equal (c2->generic_class, c1, signature_only);
+ if (mono_class_is_ginst (c1) && mono_class_is_ginst (c2))
+ return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1), mono_class_get_generic_class (c2), signature_only);
+ if (mono_class_is_ginst (c1) && mono_class_is_gtd (c2))
+ return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1), c2, signature_only);
+ if (mono_class_is_gtd (c1) && mono_class_is_ginst (c2))
+ return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2), c1, signature_only);
if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
return mono_metadata_generic_param_equal_internal (
c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
MonoClass *gtd;
int offset;
- if (!field->parent->generic_class)
+ if (!mono_class_is_ginst (field->parent))
return field;
- gtd = field->parent->generic_class->container_class;
+ gtd = mono_class_get_generic_class (field->parent)->container_class;
offset = field - field->parent->fields;
return gtd->fields + offset;
}
MonoClass *gtd;
int offset;
- if (!event->parent->generic_class)
+ if (!mono_class_is_ginst (event->parent))
return event;
- gtd = event->parent->generic_class->container_class;
+ gtd = mono_class_get_generic_class (event->parent)->container_class;
offset = event - event->parent->ext->events;
return gtd->ext->events + offset;
}
MonoClass *gtd;
int offset;
- if (!property->parent->generic_class)
+ if (!mono_class_is_ginst (property->parent))
return property;
- gtd = property->parent->generic_class->container_class;
+ gtd = mono_class_get_generic_class (property->parent)->container_class;
offset = property - property->parent->ext->properties;
return gtd->ext->properties + offset;
}
#define MONO_TYPE_IS_POINTER(t) mono_type_is_pointer (t)
#define MONO_TYPE_IS_REFERENCE(t) mono_type_is_reference (t)
-#define MONO_CLASS_IS_INTERFACE(c) ((c->flags & TYPE_ATTRIBUTE_INTERFACE) || (c->byval_arg.type == MONO_TYPE_VAR) || (c->byval_arg.type == MONO_TYPE_MVAR))
+#define MONO_CLASS_IS_INTERFACE(c) ((mono_class_get_flags (c) & TYPE_ATTRIBUTE_INTERFACE) || (c->byval_arg.type == MONO_TYPE_VAR) || (c->byval_arg.type == MONO_TYPE_MVAR))
-#define MONO_CLASS_IS_IMPORT(c) ((c->flags & TYPE_ATTRIBUTE_IMPORT))
+#define MONO_CLASS_IS_IMPORT(c) ((mono_class_get_flags (c) & TYPE_ATTRIBUTE_IMPORT))
typedef struct _MonoClass MonoClass;
typedef struct _MonoDomain MonoDomain;
struct _MonoInternalThread {
MonoObject obj;
volatile int lock_thread_id; /* to be used as the pre-shifted thread id in thin locks. Used for appdomain_ref push/pop */
- HANDLE handle;
+ MonoThreadHandle *handle;
+ HANDLE native_handle;
MonoArray *cached_culture_info;
gunichar2 *name;
guint32 name_len;
gsize abort_protected_block_count;
gint32 priority;
GPtrArray *owned_mutexes;
+ MonoOSEvent *suspended;
/*
* These fields are used to avoid having to increment corlib versions
* when a new field is added to this structure.
#endif
#if defined(TARGET_ARM64)
+DECL_OFFSET (MonoContext, has_fregs)
+
DECL_OFFSET(GSharedVtCallInfo, stack_usage)
DECL_OFFSET(GSharedVtCallInfo, gsharedvt_in)
DECL_OFFSET(GSharedVtCallInfo, ret_marshal)
for (method_slot_in_interface = 0; method_slot_in_interface < iface->method.count; method_slot_in_interface++) {
MonoMethod *method;
- if (slot_num >= 0 && iface->is_inflated) {
+ if (slot_num >= 0 && mono_class_is_ginst (iface)) {
/*
* The imt slot of the method is the same as for its declaring method,
* see the comment in mono_method_get_imt_slot (), so we can
* avoid inflating methods which will be discarded by
* add_imt_builder_entry anyway.
*/
- method = mono_class_get_method_by_index (iface->generic_class->container_class, method_slot_in_interface);
+ method = mono_class_get_method_by_index (mono_class_get_generic_class (iface)->container_class, method_slot_in_interface);
if (mono_method_get_imt_slot (method) != slot_num) {
vt_slot ++;
continue;
if (!klass->vtable_size)
mono_class_setup_vtable (klass);
- if (klass->generic_class && !klass->vtable)
+ if (mono_class_is_ginst (klass) && !klass->vtable)
mono_class_check_vtable_constraints (klass, NULL);
/* Initialize klass->has_finalize */
MONO_REQ_GC_UNSAFE_MODE;
MonoVTable *vt, *pvt;
- int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
+ int i, j, vtsize, extra_interface_vtsize = 0;
+ guint32 max_interface_id;
MonoClass *k;
GSList *extra_interfaces = NULL;
MonoClass *klass = remote_class->proxy_class;
pvt->vtable [i] = NULL;
}
- if (klass->flags & TYPE_ATTRIBUTE_ABSTRACT) {
+ if (mono_class_is_abstract (klass)) {
/* create trampolines for abstract methods */
for (k = klass; k; k = k->parent) {
MonoMethod* m;
int i, j;
if (remote_class == NULL) {
- if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (extra_class)) {
key = (void **)g_malloc (sizeof(gpointer) * 3);
key [0] = GINT_TO_POINTER (2);
key [1] = mono_defaults.marshalbyrefobject_class;
key [1] = extra_class;
}
} else {
- if (extra_class != NULL && (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ if (extra_class != NULL && mono_class_is_interface (extra_class)) {
key = (void **)g_malloc (sizeof(gpointer) * (remote_class->interface_count + 3));
key [0] = GINT_TO_POINTER (remote_class->interface_count + 2);
key [1] = remote_class->proxy_class;
g_free (key);
key = mp_key;
- if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (proxy_class)) {
rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*));
rc->interface_count = 1;
rc->interfaces [0] = proxy_class;
g_free (key);
key = mp_key;
- if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (extra_class)) {
int i,j;
rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*) * (remote_class->interface_count + 1));
rc->proxy_class = remote_class->proxy_class;
tproxy = (MonoTransparentProxy*) proxy_object;
remote_class = tproxy->remote_class;
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
int i;
redo_vtable = TRUE;
for (i = 0; i < remote_class->interface_count && redo_vtable; i++)
/* check method->slot is a valid index: perform isinstance? */
if (method->slot != -1) {
- if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (method->klass)) {
if (!is_proxy) {
gboolean variance_used = FALSE;
int iface_offset = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
if (!klass->inited)
mono_class_init (klass);
- if (mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ if (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass)) {
result = mono_object_isinst_mbyref_checked (obj, klass, error);
return result;
}
vt = obj->vtable;
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
if (MONO_VTABLE_IMPLEMENTS_INTERFACE (vt, klass->interface_id)) {
return obj;
}
ji = mono_jit_info_table_find (mono_get_root_domain (), (char *)mono_get_addr_from_ftnptr (addr));
if (ji) {
method = mono_jit_info_get_method (ji);
- g_assert (!method->klass->generic_container);
+ g_assert (!mono_class_is_gtd (method->klass));
}
return mono_delegate_ctor_with_method (this_obj, target, addr, method, error);
+++ /dev/null
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MONO_METADATA_PROCESS_INTERNALS_H__
-#define __MONO_METADATA_PROCESS_INTERNALS_H__
-
-#include <config.h>
-#include <glib.h>
-
-// On Windows platform implementation of bellow methods are hosted in separate source file
-// process-windows.c or process-windows-*.c. On other platforms the implementation is still keept
-// in process.c still declared as static and in some places even inlined.
-#ifdef HOST_WIN32
-gchar*
-mono_process_quote_path (const gchar *path);
-
-gchar*
-mono_process_unquote_application_name (gchar *path);
-
-gboolean
-mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path,
- MonoString **cmd);
-#endif /* HOST_WIN32 */
-
-// On platforms not using classic WIN API support the implementation of bellow methods are hosted in separate source file
-// process-windows-*.c. On platforms using classic WIN API the implementation is still keept in process.c and still declared
-// static and in some places even inlined.
-#if !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-void
-process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error);
-
-void
-mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle,
- HANDLE stderr_handle,STARTUPINFO *startinfo);
-
-gboolean
-mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd,
- guint32 creation_flags, gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info,
- PROCESS_INFORMATION *process_info);
-#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-// Shared between all platforms and implemented in process.c.
-gboolean
-mono_process_complete_path (const gunichar2 *appname, gchar **completed);
-
-#endif /* __MONO_METADATA_PROCESS_INTERNALS_H__ */
+++ /dev/null
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MONO_METADATA_PROCESS_WINDOWS_INTERNALS_H__
-#define __MONO_METADATA_PROCESS_WINDOWS_INTERNALS_H__
-
-#include <config.h>
-#include <glib.h>
-
-#ifdef HOST_WIN32
-#include "mono/metadata/process.h"
-#include "mono/metadata/process-internals.h"
-#include "mono/metadata/object.h"
-#include "mono/metadata/object-internals.h"
-#include "mono/metadata/exception.h"
-
-// On platforms not using classic WIN API support the implementation of bellow methods are hosted in separate source file
-// process-windows-*.c. On platforms using classic WIN API the implementation is still keept in process.c and still declared
-// static and in some places even inlined.
-#if !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed);
-#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#endif /* HOST_WIN32 */
-
-#endif /* __MONO_METADATA_PROCESS_WINDOWS_INTERNALS_H__ */
+++ /dev/null
-/*
- * process-windows-uwp.c: UWP process support for Mono.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
-*/
-#include <config.h>
-#include <glib.h>
-
-#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
-#include <Windows.h>
-#include "mono/metadata/process-windows-internals.h"
-
-gboolean
-mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
-{
- g_unsupported_api ("EnumProcesses");
- *needed = 0;
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-HANDLE
-ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
-{
- HANDLE handle;
-
- /* GetCurrentProcess returns a pseudo-handle, so use
- * OpenProcess instead
- */
- handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
- if (handle == NULL)
- /* FIXME: Throw an exception */
- return NULL;
- return handle;
-}
-
-void
-process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
-{
- g_unsupported_api ("GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
-
- mono_error_init (error);
- mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
-
- SetLastError (ERROR_NOT_SUPPORTED);
-}
-
-MonoObject*
-process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
-{
- g_unsupported_api ("GetModuleInformation");
-
- mono_error_init (error);
- mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetModuleInformation");
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return NULL;
-}
-
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return NULL;
-}
-
-MonoBoolean
-ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("ShellExecuteEx");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "ShellExecuteEx");
- mono_error_set_pending_exception (&mono_error);
-
- process_info->pid = (guint32)(-ERROR_NOT_SUPPORTED);
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-MonoString *
-ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
-{
- MonoError error;
- MonoString *string;
- gunichar2 name[MAX_PATH];
- guint32 len;
-
- len = GetModuleFileName (NULL, name, G_N_ELEMENTS (name));
- if (len == 0)
- return NULL;
-
- string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
- if (!mono_error_ok (&error))
- mono_error_set_pending_exception (&error);
-
- return string;
-}
-
-void
-mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
-{
- startinfo->cb = sizeof(STARTUPINFO);
- startinfo->dwFlags = 0;
- startinfo->hStdInput = INVALID_HANDLE_VALUE;
- startinfo->hStdOutput = INVALID_HANDLE_VALUE;
- startinfo->hStdError = INVALID_HANDLE_VALUE;
- return;
-}
-
-gboolean
-mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd, guint32 creation_flags,
- gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
-{
- MonoError mono_error;
- gchar *api_name = "";
-
- if (mono_process_info->username) {
- api_name = "CreateProcessWithLogonW";
- } else {
- api_name = "CreateProcess";
- }
-
- memset (&process_info, 0, sizeof (PROCESS_INFORMATION));
- g_unsupported_api (api_name);
-
- mono_error_init (&mono_error);
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, api_name);
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
-
-#ifdef _MSC_VER
-// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
-void __mono_win32_process_windows_uwp_quiet_lnk4221(void) {}
-#endif
-#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
+++ /dev/null
-/*
- * process-windows.c: Windows process support.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-
-#if defined(HOST_WIN32)
-#include <winsock2.h>
-#include <windows.h>
-#include "mono/metadata/process-windows-internals.h"
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline gboolean
-mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
-{
- return EnumProcesses (pids, count, needed);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
-{
- MonoError error;
- MonoArray *procs;
- gboolean ret;
- DWORD needed;
- int count;
- DWORD *pids;
-
- count = 512;
- do {
- pids = g_new0 (DWORD, count);
- ret = mono_process_win_enum_processes (pids, count * sizeof (guint32), &needed);
- if (ret == FALSE) {
- MonoException *exc;
-
- g_free (pids);
- pids = NULL;
- exc = mono_get_exception_not_supported ("This system does not support EnumProcesses");
- mono_set_pending_exception (exc);
- return NULL;
- }
- if (needed < (count * sizeof (guint32)))
- break;
- g_free (pids);
- pids = NULL;
- count = (count * 3) / 2;
- } while (TRUE);
-
- count = needed / sizeof (guint32);
- procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
- if (mono_error_set_pending_exception (&error)) {
- g_free (pids);
- return NULL;
- }
-
- memcpy (mono_array_addr (procs, guint32, 0), pids, needed);
- g_free (pids);
- pids = NULL;
-
- return procs;
-}
-
-gchar*
-mono_process_quote_path (const gchar *path)
-{
- gchar *res = g_shell_quote (path);
- gchar *q = res;
- while (*q) {
- if (*q == '\'')
- *q = '\"';
- q++;
- }
- return res;
-}
-
-gchar*
-mono_process_unquote_application_name (gchar *appname)
-{
- size_t len = strlen (appname);
- if (len) {
- if (appname[len-1] == '\"')
- appname[len-1] = '\0';
- if (appname[0] == '\"')
- appname++;
- }
-
- return appname;
-}
-
-gboolean
-mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
-{
- gchar *spath = NULL;
- gchar *new_cmd, *cmd_utf8;
- MonoError mono_error;
-
- *shell_path = NULL;
- *cmd = proc_start_info->arguments;
-
- mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
- if (spath != NULL) {
- /* Seems like our CreateProcess does not work as the windows one.
- * This hack is needed to deal with paths containing spaces */
- if (*cmd) {
- cmd_utf8 = mono_string_to_utf8_checked (*cmd, &mono_error);
- if (!mono_error_set_pending_exception (&mono_error)) {
- new_cmd = g_strdup_printf ("%s %s", spath, cmd_utf8);
- *cmd = mono_string_new_wrapper (new_cmd);
- g_free (cmd_utf8);
- g_free (new_cmd);
- } else {
- *cmd = NULL;
- }
- }
- else {
- *cmd = mono_string_new_wrapper (spath);
- }
-
- g_free (spath);
- }
-
- return (*cmd != NULL) ? TRUE : FALSE;
-}
-#endif /* HOST_WIN32 */
+++ /dev/null
-/*
- * process.c: System.Diagnostics.Process support
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * Copyright 2002 Ximian, Inc.
- * Copyright 2002-2006 Novell, Inc.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#include <glib.h>
-#include <string.h>
-
-#include <mono/metadata/object-internals.h>
-#include <mono/metadata/process.h>
-#include <mono/metadata/process-internals.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/image.h>
-#include <mono/metadata/cil-coff.h>
-#include <mono/metadata/exception.h>
-#include <mono/metadata/threadpool-ms-io.h>
-#include <mono/utils/strenc.h>
-#include <mono/utils/mono-proclib.h>
-#include <mono/io-layer/io-layer.h>
-/* FIXME: fix this code to not depend so much on the internals */
-#include <mono/metadata/class-internals.h>
-#include <mono/utils/w32handle.h>
-
-#define LOGDEBUG(...)
-/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
-
-#if defined(HOST_WIN32) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-#include <shellapi.h>
-#endif
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
-{
- HANDLE handle;
-
- /* GetCurrentProcess returns a pseudo-handle, so use
- * OpenProcess instead
- */
- handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
- if (handle == NULL)
- /* FIXME: Throw an exception */
- return NULL;
- return handle;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
-
-static MonoImage *system_assembly;
-
-static void
-stash_system_assembly (MonoObject *obj)
-{
- if (!system_assembly)
- system_assembly = obj->vtable->klass->image;
-}
-
-//Hand coded version that loads from system
-static MonoClass*
-mono_class_get_file_version_info_class (void)
-{
- static MonoClass *tmp_class;
- MonoClass *klass = tmp_class;
- if (!klass) {
- klass = mono_class_load_from_name (system_assembly, "System.Diagnostics", "FileVersionInfo");
- mono_memory_barrier ();
- tmp_class = klass;
- }
- return klass;
-}
-
-static MonoClass*
-mono_class_get_process_module_class (void)
-{
- static MonoClass *tmp_class;
- MonoClass *klass = tmp_class;
- if (!klass) {
- klass = mono_class_load_from_name (system_assembly, "System.Diagnostics", "ProcessModule");
- mono_memory_barrier ();
- tmp_class = klass;
- }
- return klass;
-}
-
-static guint32
-unicode_chars (const gunichar2 *str)
-{
- guint32 len;
-
- for (len = 0; str [len] != '\0'; ++len)
- ;
- return len;
-}
-
-static void
-process_set_field_object (MonoObject *obj, const gchar *fieldname,
- MonoObject *data)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to object at %p", __func__, fieldname, data));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, data);
-}
-
-static void
-process_set_field_string (MonoObject *obj, const gchar *fieldname,
- const gunichar2 *val, guint32 len, MonoError *error)
-{
- MonoClassField *field;
- MonoString *string;
-
- mono_error_init (error);
-
- LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, g_utf16_to_utf8 (val, len, NULL, NULL, NULL)));
-
- string = mono_string_new_utf16_checked (mono_object_domain (obj), val, len, error);
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
-}
-
-static void
-process_set_field_string_char (MonoObject *obj, const gchar *fieldname,
- const gchar *val)
-{
- MonoClassField *field;
- MonoString *string;
-
- LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, val));
-
- string = mono_string_new (mono_object_domain (obj), val);
-
- field = mono_class_get_field_from_name (mono_object_class (obj), fieldname);
- mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
-}
-
-static void
-process_set_field_int (MonoObject *obj, const gchar *fieldname,
- guint32 val)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to %d", __func__,fieldname, val));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- *(guint32 *)(((char *)obj) + field->offset)=val;
-}
-
-static void
-process_set_field_intptr (MonoObject *obj, const gchar *fieldname,
- gpointer val)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to %p", __func__, fieldname, val));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- *(gpointer *)(((char *)obj) + field->offset) = val;
-}
-
-static void
-process_set_field_bool (MonoObject *obj, const gchar *fieldname,
- gboolean val)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to %s", __func__, fieldname, val ? "TRUE":"FALSE"));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- *(guint8 *)(((char *)obj) + field->offset) = val;
-}
-
-#define SFI_COMMENTS "\\StringFileInfo\\%02X%02X%02X%02X\\Comments"
-#define SFI_COMPANYNAME "\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName"
-#define SFI_FILEDESCRIPTION "\\StringFileInfo\\%02X%02X%02X%02X\\FileDescription"
-#define SFI_FILEVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\FileVersion"
-#define SFI_INTERNALNAME "\\StringFileInfo\\%02X%02X%02X%02X\\InternalName"
-#define SFI_LEGALCOPYRIGHT "\\StringFileInfo\\%02X%02X%02X%02X\\LegalCopyright"
-#define SFI_LEGALTRADEMARKS "\\StringFileInfo\\%02X%02X%02X%02X\\LegalTrademarks"
-#define SFI_ORIGINALFILENAME "\\StringFileInfo\\%02X%02X%02X%02X\\OriginalFilename"
-#define SFI_PRIVATEBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\PrivateBuild"
-#define SFI_PRODUCTNAME "\\StringFileInfo\\%02X%02X%02X%02X\\ProductName"
-#define SFI_PRODUCTVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\ProductVersion"
-#define SFI_SPECIALBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\SpecialBuild"
-#define EMPTY_STRING (gunichar2*)"\000\000"
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static void
-process_module_string_read (MonoObject *filever, gpointer data,
- const gchar *fieldname, guchar lang_hi, guchar lang_lo,
- const gchar *key, MonoError *error)
-{
- gchar *lang_key_utf8;
- gunichar2 *lang_key, *buffer;
- UINT chars;
-
- mono_error_init (error);
-
- lang_key_utf8 = g_strdup_printf (key, lang_lo, lang_hi, 0x04, 0xb0);
-
- LOGDEBUG (g_message ("%s: asking for [%s]", __func__, lang_key_utf8));
-
- lang_key = g_utf8_to_utf16 (lang_key_utf8, -1, NULL, NULL, NULL);
-
- if (VerQueryValue (data, lang_key, (gpointer *)&buffer, &chars) && chars > 0) {
- LOGDEBUG (g_message ("%s: found %d chars of [%s]", __func__, chars, g_utf16_to_utf8 (buffer, chars, NULL, NULL, NULL)));
- /* chars includes trailing null */
- process_set_field_string (filever, fieldname, buffer, chars - 1, error);
- } else {
- process_set_field_string (filever, fieldname, EMPTY_STRING, 0, error);
- }
-
- g_free (lang_key);
- g_free (lang_key_utf8);
-}
-
-typedef struct {
- const char *name;
- const char *id;
-} StringTableEntry;
-
-static StringTableEntry stringtable_entries [] = {
- { "comments", SFI_COMMENTS },
- { "companyname", SFI_COMPANYNAME },
- { "filedescription", SFI_FILEDESCRIPTION },
- { "fileversion", SFI_FILEVERSION },
- { "internalname", SFI_INTERNALNAME },
- { "legalcopyright", SFI_LEGALCOPYRIGHT },
- { "legaltrademarks", SFI_LEGALTRADEMARKS },
- { "originalfilename", SFI_ORIGINALFILENAME },
- { "privatebuild", SFI_PRIVATEBUILD },
- { "productname", SFI_PRODUCTNAME },
- { "productversion", SFI_PRODUCTVERSION },
- { "specialbuild", SFI_SPECIALBUILD }
-};
-
-static void
-process_module_stringtable (MonoObject *filever, gpointer data,
- guchar lang_hi, guchar lang_lo, MonoError *error)
-{
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
- process_module_string_read (filever, data, stringtable_entries [i].name, lang_hi, lang_lo,
- stringtable_entries [i].id, error);
- return_if_nok (error);
- }
-}
-
-static void
-process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
-{
- DWORD verinfohandle;
- VS_FIXEDFILEINFO *ffi;
- gpointer data;
- DWORD datalen;
- guchar *trans_data;
- gunichar2 *query;
- UINT ffi_size, trans_size;
- BOOL ok;
- gunichar2 lang_buf[128];
- guint32 lang, lang_count;
-
- mono_error_init (error);
-
- datalen = GetFileVersionInfoSize (filename, &verinfohandle);
- if (datalen) {
- data = g_malloc0 (datalen);
- ok = GetFileVersionInfo (filename, verinfohandle, datalen,
- data);
- if (ok) {
- query = g_utf8_to_utf16 ("\\", -1, NULL, NULL, NULL);
- if (query == NULL) {
- g_free (data);
- return;
- }
-
- if (VerQueryValue (data, query, (gpointer *)&ffi,
- &ffi_size)) {
- LOGDEBUG (g_message ("%s: recording assembly: FileName [%s] FileVersionInfo [%d.%d.%d.%d]", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), HIWORD (ffi->dwFileVersionMS), LOWORD (ffi->dwFileVersionMS), HIWORD (ffi->dwFileVersionLS), LOWORD (ffi->dwFileVersionLS)));
-
- process_set_field_int (filever, "filemajorpart", HIWORD (ffi->dwFileVersionMS));
- process_set_field_int (filever, "fileminorpart", LOWORD (ffi->dwFileVersionMS));
- process_set_field_int (filever, "filebuildpart", HIWORD (ffi->dwFileVersionLS));
- process_set_field_int (filever, "fileprivatepart", LOWORD (ffi->dwFileVersionLS));
-
- process_set_field_int (filever, "productmajorpart", HIWORD (ffi->dwProductVersionMS));
- process_set_field_int (filever, "productminorpart", LOWORD (ffi->dwProductVersionMS));
- process_set_field_int (filever, "productbuildpart", HIWORD (ffi->dwProductVersionLS));
- process_set_field_int (filever, "productprivatepart", LOWORD (ffi->dwProductVersionLS));
-
- process_set_field_bool (filever, "isdebug", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_DEBUG) != 0);
- process_set_field_bool (filever, "isprerelease", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRERELEASE) != 0);
- process_set_field_bool (filever, "ispatched", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PATCHED) != 0);
- process_set_field_bool (filever, "isprivatebuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRIVATEBUILD) != 0);
- process_set_field_bool (filever, "isspecialbuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_SPECIALBUILD) != 0);
- }
- g_free (query);
-
- query = g_utf8_to_utf16 ("\\VarFileInfo\\Translation", -1, NULL, NULL, NULL);
- if (query == NULL) {
- g_free (data);
- return;
- }
-
- if (VerQueryValue (data, query,
- (gpointer *)&trans_data,
- &trans_size)) {
- /* use the first language ID we see
- */
- if (trans_size >= 4) {
- LOGDEBUG (g_message("%s: %s has 0x%0x 0x%0x 0x%0x 0x%0x", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), trans_data[0], trans_data[1], trans_data[2], trans_data[3]));
- lang = (trans_data[0]) |
- (trans_data[1] << 8) |
- (trans_data[2] << 16) |
- (trans_data[3] << 24);
- /* Only give the lower 16 bits
- * to VerLanguageName, as
- * Windows gets confused
- * otherwise
- */
- lang_count = VerLanguageName (lang & 0xFFFF, lang_buf, 128);
- if (lang_count) {
- process_set_field_string (filever, "language", lang_buf, lang_count, error);
- return_if_nok (error);
- }
- process_module_stringtable (filever, data, trans_data[0], trans_data[1], error);
- return_if_nok (error);
- }
- } else {
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
- /* No strings, so set every field to
- * the empty string
- */
- process_set_field_string (filever,
- stringtable_entries [i].name,
- EMPTY_STRING, 0, error);
- return_if_nok (error);
- }
-
- /* And language seems to be set to
- * en_US according to bug 374600
- */
- lang_count = VerLanguageName (0x0409, lang_buf, 128);
- if (lang_count) {
- process_set_field_string (filever, "language", lang_buf, lang_count, error);
- return_if_nok (error);
- }
- }
-
- g_free (query);
- }
- g_free (data);
- }
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-static void
-process_get_assembly_fileversion (MonoObject *filever, MonoAssembly *assembly)
-{
- process_set_field_int (filever, "filemajorpart", assembly->aname.major);
- process_set_field_int (filever, "fileminorpart", assembly->aname.minor);
- process_set_field_int (filever, "filebuildpart", assembly->aname.build);
-}
-
-static MonoObject*
-get_process_module (MonoAssembly *assembly, MonoClass *proc_class, MonoError *error)
-{
- MonoObject *item, *filever;
- MonoDomain *domain = mono_domain_get ();
- char *filename;
- const char *modulename = assembly->aname.name;
-
- mono_error_init (error);
-
- /* Build a System.Diagnostics.ProcessModule with the data.
- */
- item = mono_object_new_checked (domain, proc_class, error);
- return_val_if_nok (error, NULL);
- filever = mono_object_new_checked (domain, mono_class_get_file_version_info_class (), error);
- return_val_if_nok (error, NULL);
-
- filename = g_strdup_printf ("[In Memory] %s", modulename);
-
- process_get_assembly_fileversion (filever, assembly);
- process_set_field_string_char (filever, "filename", filename);
- process_set_field_object (item, "version_info", filever);
-
- process_set_field_intptr (item, "baseaddr", assembly->image->raw_data);
- process_set_field_int (item, "memory_size", assembly->image->raw_data_len);
- process_set_field_string_char (item, "filename", filename);
- process_set_field_string_char (item, "modulename", modulename);
-
- g_free (filename);
-
- return item;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static MonoObject*
-process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
-{
- MonoObject *item, *filever;
- MonoDomain *domain = mono_domain_get ();
- MODULEINFO modinfo;
- BOOL ok;
-
- mono_error_init (error);
-
- /* Build a System.Diagnostics.ProcessModule with the data.
- */
- item = mono_object_new_checked (domain, proc_class, error);
- return_val_if_nok (error, NULL);
- filever = mono_object_new_checked (domain, mono_class_get_file_version_info_class (), error);
- return_val_if_nok (error, NULL);
-
- process_get_fileversion (filever, filename, error);
- return_val_if_nok (error, NULL);
-
- process_set_field_string (filever, "filename", filename,
- unicode_chars (filename), error);
- return_val_if_nok (error, NULL);
- ok = GetModuleInformation (process, mod, &modinfo, sizeof(MODULEINFO));
- if (ok) {
- process_set_field_intptr (item, "baseaddr",
- modinfo.lpBaseOfDll);
- process_set_field_intptr (item, "entryaddr",
- modinfo.EntryPoint);
- process_set_field_int (item, "memory_size",
- modinfo.SizeOfImage);
- }
- process_set_field_string (item, "filename", filename,
- unicode_chars (filename), error);
- return_val_if_nok (error, NULL);
- process_set_field_string (item, "modulename", modulename,
- unicode_chars (modulename), error);
- return_val_if_nok (error, NULL);
- process_set_field_object (item, "version_info", filever);
-
- return item;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-static GPtrArray*
-get_domain_assemblies (MonoDomain *domain)
-{
- GSList *tmp;
- GPtrArray *assemblies;
-
- /*
- * Make a copy of the list of assemblies because we can't hold the assemblies
- * lock while creating objects etc.
- */
- assemblies = g_ptr_array_new ();
- mono_domain_assemblies_lock (domain);
- for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
- MonoAssembly *ass = (MonoAssembly *)tmp->data;
- if (ass->image->fileio_used)
- continue;
- g_ptr_array_add (assemblies, ass);
- }
- mono_domain_assemblies_unlock (domain);
-
- return assemblies;
-}
-
-/* Returns an array of System.Diagnostics.ProcessModule */
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
-{
- MonoError error;
- MonoArray *temp_arr = NULL;
- MonoArray *arr;
- HMODULE mods[1024];
- gunichar2 filename[MAX_PATH];
- gunichar2 modname[MAX_PATH];
- DWORD needed;
- guint32 count = 0, module_count = 0, assembly_count = 0;
- guint32 i, num_added = 0;
- GPtrArray *assemblies = NULL;
-
- stash_system_assembly (this_obj);
-
- if (GetProcessId (process) == mono_process_current_pid ()) {
- assemblies = get_domain_assemblies (mono_domain_get ());
- assembly_count = assemblies->len;
- }
-
- if (EnumProcessModules (process, mods, sizeof(mods), &needed)) {
- module_count += needed / sizeof(HMODULE);
- }
-
- count = module_count + assembly_count;
- temp_arr = mono_array_new_checked (mono_domain_get (), mono_class_get_process_module_class (), count, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- for (i = 0; i < module_count; i++) {
- if (GetModuleBaseName (process, mods[i], modname, MAX_PATH) &&
- GetModuleFileNameEx (process, mods[i], filename, MAX_PATH)) {
- MonoObject *module = process_add_module (process, mods[i],
- filename, modname, mono_class_get_process_module_class (), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
- mono_array_setref (temp_arr, num_added++, module);
- }
- }
-
- if (assemblies) {
- for (i = 0; i < assembly_count; i++) {
- MonoAssembly *ass = (MonoAssembly *)g_ptr_array_index (assemblies, i);
- MonoObject *module = get_process_module (ass, mono_class_get_process_module_class (), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
- mono_array_setref (temp_arr, num_added++, module);
- }
- g_ptr_array_free (assemblies, TRUE);
- }
-
- if (count == num_added) {
- arr = temp_arr;
- } else {
- /* shorter version of the array */
- arr = mono_array_new_checked (mono_domain_get (), mono_class_get_process_module_class (), num_added, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- for (i = 0; i < num_added; i++)
- mono_array_setref (arr, i, mono_array_get (temp_arr, MonoObject*, i));
- }
-
- return arr;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-void
-ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename)
-{
- MonoError error;
-
- stash_system_assembly (this_obj);
-
- process_get_fileversion (this_obj, mono_string_chars (filename), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
- process_set_field_string (this_obj, "filename",
- mono_string_chars (filename),
- mono_string_length (filename), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
-}
-
-/* Only used when UseShellExecute is false */
-#ifndef HOST_WIN32
-static inline gchar *
-mono_process_quote_path (const gchar *path)
-{
- return g_shell_quote (path);
-}
-
-static inline gchar *
-mono_process_unquote_application_name (gchar *path)
-{
- return path;
-}
-#endif /* !HOST_WIN32 */
-
-/* Only used when UseShellExecute is false */
-gboolean
-mono_process_complete_path (const gunichar2 *appname, gchar **completed)
-{
- gchar *utf8app, *utf8appmemory;
- gchar *found;
-
- utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
- utf8app = mono_process_unquote_application_name (utf8appmemory);
-
- if (g_path_is_absolute (utf8app)) {
- *completed = mono_process_quote_path (utf8app);
- g_free (utf8appmemory);
- return TRUE;
- }
-
- if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
- *completed = mono_process_quote_path (utf8app);
- g_free (utf8appmemory);
- return TRUE;
- }
-
- found = g_find_program_in_path (utf8app);
- if (found == NULL) {
- *completed = NULL;
- g_free (utf8appmemory);
- return FALSE;
- }
-
- *completed = mono_process_quote_path (found);
- g_free (found);
- g_free (utf8appmemory);
- return TRUE;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-MonoBoolean
-ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
-{
- SHELLEXECUTEINFO shellex = {0};
- gboolean ret;
-
- shellex.cbSize = sizeof(SHELLEXECUTEINFO);
- shellex.fMask = (gulong)(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE);
- shellex.nShow = (gulong)proc_start_info->window_style;
- shellex.nShow = (gulong)((shellex.nShow == 0) ? 1 : (shellex.nShow == 1 ? 0 : shellex.nShow));
-
- if (proc_start_info->filename != NULL) {
- shellex.lpFile = mono_string_chars (proc_start_info->filename);
- }
-
- if (proc_start_info->arguments != NULL) {
- shellex.lpParameters = mono_string_chars (proc_start_info->arguments);
- }
-
- if (proc_start_info->verb != NULL &&
- mono_string_length (proc_start_info->verb) != 0) {
- shellex.lpVerb = mono_string_chars (proc_start_info->verb);
- }
-
- if (proc_start_info->working_directory != NULL &&
- mono_string_length (proc_start_info->working_directory) != 0) {
- shellex.lpDirectory = mono_string_chars (proc_start_info->working_directory);
- }
-
- if (proc_start_info->error_dialog) {
- shellex.hwnd = proc_start_info->error_dialog_parent_handle;
- } else {
- shellex.fMask = (gulong)(shellex.fMask | SEE_MASK_FLAG_NO_UI);
- }
-
- ret = ShellExecuteEx (&shellex);
- if (ret == FALSE) {
- process_info->pid = -GetLastError ();
- } else {
- process_info->process_handle = shellex.hProcess;
- process_info->thread_handle = NULL;
-#if !defined(MONO_CROSS_COMPILE)
- process_info->pid = GetProcessId (shellex.hProcess);
-#else
- process_info->pid = 0;
-#endif
- process_info->tid = 0;
- }
-
- return ret;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline void
-mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
-{
- startinfo->cb = sizeof(STARTUPINFO);
- startinfo->dwFlags = STARTF_USESTDHANDLES;
- startinfo->hStdInput = stdin_handle;
- startinfo->hStdOutput = stdout_handle;
- startinfo->hStdError = stderr_handle;
- return;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#ifndef HOST_WIN32
-static gboolean
-mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
-{
- gchar *spath = NULL;
-
- *shell_path = NULL;
- *cmd = proc_start_info->arguments;
-
- mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
- if (spath != NULL) {
- *shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
- g_free (spath);
- }
-
- return (*shell_path != NULL) ? TRUE : FALSE;
-}
-#endif /* !HOST_WIN32 */
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static gboolean
-mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path,
- MonoString *cmd, guint32 creation_flags, gchar *env_vars,
- gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
-{
- gboolean result = FALSE;
-
- if (mono_process_info->username) {
- guint32 logon_flags = mono_process_info->load_user_profile ? LOGON_WITH_PROFILE : 0;
-
- result = CreateProcessWithLogonW (mono_string_chars (mono_process_info->username),
- mono_process_info->domain ? mono_string_chars (mono_process_info->domain) : NULL,
- (const gunichar2 *)mono_process_info->password,
- logon_flags,
- shell_path,
- cmd ? mono_string_chars (cmd) : NULL,
- creation_flags,
- env_vars, dir, start_info, process_info);
-
- } else {
-
- result = CreateProcess (shell_path,
- cmd ? mono_string_chars (cmd): NULL,
- NULL,
- NULL,
- TRUE,
- creation_flags,
- env_vars,
- dir,
- start_info,
- process_info);
-
- }
-
- return result;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-MonoBoolean
-ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInfo *proc_start_info, HANDLE stdin_handle,
- HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info)
-{
- gboolean ret;
- gunichar2 *dir;
- STARTUPINFO startinfo={0};
- PROCESS_INFORMATION procinfo;
- gunichar2 *shell_path = NULL;
- gchar *env_vars = NULL;
- MonoString *cmd = NULL;
- guint32 creation_flags;
-
- mono_process_init_startup_info (stdin_handle, stdout_handle, stderr_handle, &startinfo);
-
- creation_flags = CREATE_UNICODE_ENVIRONMENT;
- if (proc_start_info->create_no_window)
- creation_flags |= CREATE_NO_WINDOW;
-
- if (mono_process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
- process_info->pid = -ERROR_FILE_NOT_FOUND;
- return FALSE;
- }
-
- if (process_info->env_keys) {
- gint i, len;
- MonoString *ms;
- MonoString *key, *value;
- gunichar2 *str, *ptr;
- gunichar2 *equals16;
-
- for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
- ms = mono_array_get (process_info->env_values, MonoString *, i);
- if (ms == NULL)
- continue;
-
- len += mono_string_length (ms) * sizeof (gunichar2);
- ms = mono_array_get (process_info->env_keys, MonoString *, i);
- len += mono_string_length (ms) * sizeof (gunichar2);
- len += 2 * sizeof (gunichar2);
- }
-
- equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
- ptr = str = g_new0 (gunichar2, len + 1);
- for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
- value = mono_array_get (process_info->env_values, MonoString *, i);
- if (value == NULL)
- continue;
-
- key = mono_array_get (process_info->env_keys, MonoString *, i);
- memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
- ptr += mono_string_length (key);
-
- memcpy (ptr, equals16, sizeof (gunichar2));
- ptr++;
-
- memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
- ptr += mono_string_length (value);
- ptr++;
- }
-
- g_free (equals16);
- env_vars = (gchar *) str;
- }
-
- /* The default dir name is "". Turn that into NULL to mean
- * "current directory"
- */
- if (proc_start_info->working_directory == NULL || mono_string_length (proc_start_info->working_directory) == 0)
- dir = NULL;
- else
- dir = mono_string_chars (proc_start_info->working_directory);
-
- ret = mono_process_create_process (process_info, shell_path, cmd, creation_flags, env_vars, dir, &startinfo, &procinfo);
-
- g_free (env_vars);
- if (shell_path != NULL)
- g_free (shell_path);
-
- if (ret) {
- process_info->process_handle = procinfo.hProcess;
- /*process_info->thread_handle=procinfo.hThread;*/
- process_info->thread_handle = NULL;
- if (procinfo.hThread != NULL && procinfo.hThread != INVALID_HANDLE_VALUE)
- CloseHandle (procinfo.hThread);
- process_info->pid = procinfo.dwProcessId;
- process_info->tid = procinfo.dwThreadId;
- } else {
- process_info->pid = -GetLastError ();
- }
-
- return ret;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-MonoString *
-ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
-{
- MonoError error;
- MonoString *string;
- gunichar2 name[MAX_PATH];
- guint32 len;
- gboolean ok;
- HMODULE mod;
- DWORD needed;
-
- ok = EnumProcessModules (process, &mod, sizeof(mod), &needed);
- if (!ok)
- return NULL;
-
- len = GetModuleBaseName (process, mod, name, MAX_PATH);
-
- if (len == 0)
- return NULL;
-
- LOGDEBUG (g_message ("%s: process name is [%s]", __func__, g_utf16_to_utf8 (name, -1, NULL, NULL, NULL)));
-
- string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
- if (!mono_error_ok (&error))
- mono_error_set_pending_exception (&error);
-
- return string;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#ifndef HOST_WIN32
-/* Returns an array of pids */
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
-{
- MonoError error;
- MonoArray *procs;
- gpointer *pidarray;
- int i, count;
-
- pidarray = mono_process_list (&count);
- if (!pidarray) {
- mono_set_pending_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses"));
- return NULL;
- }
- procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
- if (mono_error_set_pending_exception (&error)) {
- g_free (pidarray);
- return NULL;
- }
- if (sizeof (guint32) == sizeof (gpointer)) {
- memcpy (mono_array_addr (procs, guint32, 0), pidarray, count * sizeof (gint32));
- } else {
- for (i = 0; i < count; ++i)
- *(mono_array_addr (procs, guint32, i)) = GPOINTER_TO_UINT (pidarray [i]);
- }
- g_free (pidarray);
-
- return procs;
-}
-#endif /* !HOST_WIN32 */
-
-gint64
-ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error)
-{
- MonoProcessError perror;
- guint64 res;
-
- res = mono_process_get_data_with_error (GINT_TO_POINTER (pid), (MonoProcessData)data_type, &perror);
- if (error)
- *error = perror;
- return res;
-}
+++ /dev/null
-/*
- * process.h: System.Diagnostics.Process support
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _MONO_METADATA_PROCESS_H_
-#define _MONO_METADATA_PROCESS_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/metadata/object.h>
-#include <mono/io-layer/io-layer.h>
-#include "mono/utils/mono-compiler.h"
-
-typedef struct
-{
- HANDLE process_handle;
- HANDLE thread_handle;
- guint32 pid; /* Contains GetLastError () on failure */
- guint32 tid;
- MonoArray *env_keys;
- MonoArray *env_values;
- MonoString *username;
- MonoString *domain;
- gpointer password; /* BSTR from SecureString in 2.0 profile */
- MonoBoolean load_user_profile;
-} MonoProcInfo;
-
-typedef struct
-{
- MonoObject object;
- MonoString *filename;
- MonoString *arguments;
- MonoString *working_directory;
- MonoString *verb;
- guint32 window_style;
- MonoBoolean error_dialog;
- gpointer error_dialog_parent_handle;
- MonoBoolean use_shell_execute;
- MonoString *username;
- MonoString *domain;
- MonoObject *password; /* SecureString in 2.0 profile, dummy in 1.x */
- MonoString *password_in_clear_text;
- MonoBoolean load_user_profile;
- MonoBoolean redirect_standard_input;
- MonoBoolean redirect_standard_output;
- MonoBoolean redirect_standard_error;
- MonoObject *encoding_stdout;
- MonoObject *encoding_stderr;
- MonoBoolean create_no_window;
- MonoObject *weak_parent_process;
- MonoObject *envVars;
-} MonoProcessStartInfo;
-
-G_BEGIN_DECLS
-
-HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid);
-MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void);
-MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process);
-void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename);
-MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_handle);
-MonoBoolean ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInfo *proc_start_info, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_handle);
-MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process);
-gint64 ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error);
-
-G_END_DECLS
-
-#endif /* _MONO_METADATA_PROCESS_H_ */
-
mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error);
MonoCustomAttrInfo*
-mono_custom_attrs_from_index_checked (MonoImage *image, uint32_t idx, MonoError *error);
+mono_custom_attrs_from_index_checked (MonoImage *image, uint32_t idx, gboolean ignore_missing, MonoError *error);
MonoCustomAttrInfo*
mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error);
MonoCustomAttrInfo*
mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error);
MonoCustomAttrInfo*
-mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error);
+mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error);
MonoCustomAttrInfo*
mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error);
MonoCustomAttrInfo*
#include <mono/utils/mono-string.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/checked-build.h>
+#include <mono/utils/mono-counters.h>
static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
+
+static int class_ref_info_handle_count;
+
void
mono_reflection_init (void)
{
mono_reflection_emit_init ();
+
+ mono_counters_register ("MonoClass::ref_info_handle count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ref_info_handle_count);
+
}
/*
MONO_REQ_GC_UNSAFE_MODE;
klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
+ ++class_ref_info_handle_count;
g_assert (klass->ref_info_handle != 0);
}
return type;
gtd = gclass->container_class;
- gcontainer = gtd->generic_container;
+ gcontainer = mono_class_get_generic_container (gtd);
argv = g_newa (MonoType*, ginst->type_argc);
for (i = 0; i < ginst->type_argc; ++i) {
}
klass = mono_class_from_mono_type (t);
- if (!klass->generic_container) {
+ if (!mono_class_is_gtd (klass)) {
mono_loader_unlock ();
mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
return NULL;
}
+ guint gtd_type_argc = mono_class_get_generic_container (klass)->type_argc;
+ if (gtd_type_argc != type_argc) {
+ mono_loader_unlock ();
+ mono_error_set_argument (error, "types", "The generic type definition needs %d type arguments, but was instantiated with %d ", gtd_type_argc, type_argc);
+ return NULL;
+ }
+
+
if (klass->wastypebuilder)
is_dynamic = TRUE;
MonoGenericClass *gclass;
MonoGenericInst *inst;
- g_assert (klass->generic_container);
+ g_assert (mono_class_is_gtd (klass));
inst = mono_metadata_get_generic_inst (type_argc, types);
gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
ginst = mono_metadata_get_generic_inst (count, type_argv);
g_free (type_argv);
- tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+ tmp_context.class_inst = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->context.class_inst : NULL;
tmp_context.method_inst = ginst;
inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
guint32
mono_declsec_flags_from_class (MonoClass *klass)
{
- if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
+ if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_HAS_SECURITY) {
if (!klass->ext || !klass->ext->declsec_flags) {
guint32 idx;
fwrite (buffer_orig, 1, buffer - buffer_orig, f);
g_free (buffer_orig);
+ fclose (f);
return TRUE;
}
return sgen_has_managed_allocator ();
}
+static gboolean
+ip_in_critical_region (MonoDomain *domain, gpointer ip)
+{
+ MonoJitInfo *ji;
+ MonoMethod *method;
+
+ /*
+ * We pass false for 'try_aot' so this becomes async safe.
+ * It won't find aot methods whose jit info is not yet loaded,
+ * so we preload their jit info in the JIT.
+ */
+ ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE);
+ if (!ji)
+ return FALSE;
+
+ method = mono_jit_info_get_method (ji);
+
+ return mono_runtime_is_critical_method (method) || sgen_is_critical_method (method);
+}
+
+gboolean
+mono_gc_is_critical_method (MonoMethod *method)
+{
+ return sgen_is_critical_method (method);
+}
+
#ifndef DISABLE_JIT
static void
UNLOCK_GC;
}
-static gboolean
-is_critical_method (MonoMethod *method)
-{
- return mono_runtime_is_critical_method (method) || sgen_is_critical_method (method);
-}
-
static gboolean
thread_in_critical_region (SgenThreadInfo *info)
{
cb.thread_detach = sgen_thread_detach;
cb.thread_unregister = sgen_thread_unregister;
cb.thread_attach = sgen_thread_attach;
- cb.mono_method_is_critical = (gboolean (*)(void *))is_critical_method;
cb.mono_thread_in_critical_region = thread_in_critical_region;
+ cb.ip_in_critical_region = ip_in_critical_region;
mono_threads_init (&cb, sizeof (SgenThreadInfo));
/* FIXME the bridge check can be quite expensive, cache it at the class level. */
/* An array of a sealed type that is not a bridge will never get to a bridge */
- if ((elem_class->flags & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
+ if ((mono_class_get_flags (elem_class) & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
SGEN_LOG (6, "class %s is opaque\n", klass->name);
return GC_BRIDGE_OPAQUE_CLASS;
}
/* FIXME the bridge check can be quite expensive, cache it at the class level. */
/* An array of a sealed type that is not a bridge will never get to a bridge */
- if ((elem_class->flags & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
+ if ((mono_class_get_flags (elem_class) & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
SGEN_LOG (6, "class %s is opaque\n", klass->name);
return GC_BRIDGE_OPAQUE_CLASS;
}
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/networking.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
#include <time.h>
#ifdef HAVE_SYS_TIME_H
case MONO_TYPE_CLASS: {
MonoClass *k = mono_class_from_mono_type (type);
- if (k->generic_container) {
- MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
+ if (mono_class_is_gtd (k)) {
+ MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, mono_class_get_generic_container (k)->context.class_inst, TRUE);
encode_generic_class (assembly, gclass, buf);
} else {
/*
return idx;
}
case MONO_TYPE_GENERICINST:
- *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
+ *ret_type = mono_class_get_generic_class (val->vtable->klass)->container_class->byval_arg.type;
goto handle_enum;
default:
g_error ("we don't encode constant type 0x%02x yet", *ret_type);
goto fail;
/* encode custom attributes before the type */
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
typespec = create_typespec (assembly, type);
if (typespec) {
MonoGenericClass *gclass;
- gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
+ gclass = mono_metadata_lookup_generic_class (klass, mono_class_get_generic_container (klass)->context.class_inst, TRUE);
encode_generic_class (assembly, gclass, &buf);
} else {
encode_type (assembly, type, &buf);
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE: {
MonoClass *k = mono_class_from_mono_type (type);
- if (!k || !k->generic_container) {
+ if (!k || !mono_class_is_gtd (k)) {
sigbuffer_free (&buf);
return 0;
}
if (token)
return token;
klass = mono_class_from_mono_type (type);
- if (!klass)
- klass = mono_class_from_mono_type (type);
/*
* If it's in the same module and not a generic type parameter:
guint32 *values;
guint32 visib, res;
- visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ visib = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
return 0;
alloc_table (table, table->rows);
values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
- values [MONO_EXP_TYPE_FLAGS] = klass->flags;
+ values [MONO_EXP_TYPE_FLAGS] = mono_class_get_flags (klass);
values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
if (klass->nested_in)
values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
- if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
+ if (mono_class_is_public (klass))
mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
}
}
} else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
!strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- g_assert (m->klass->generic_class || m->klass->generic_container);
+ g_assert (mono_class_is_ginst (m->klass) || mono_class_is_gtd (m->klass));
continue;
} else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
g_assert_not_reached ();
return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
ta = klass->image->assembly;
if (assembly_is_dynamic (ta) || (ta == ass)) {
- if (klass->generic_class || klass->generic_container)
+ if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
/* For generic type definitions, we want T, while REFLECTION returns T<K> */
return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
else
static gboolean
is_field_on_inst (MonoClassField *field)
{
- return field->parent->generic_class && field->parent->generic_class->is_dynamic;
+ return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
}
#ifndef DISABLE_REFLECTION_EMIT
if (token)
return token;
- if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
+ if (mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->container_class && mono_class_get_generic_class (field->parent)->container_class->fields) {
int index = field - field->parent->fields;
- type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
+ type = mono_field_get_type (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
} else {
type = mono_field_get_type (field);
}
return_val_if_nok (error, 0);
MonoClass *mc = mono_class_from_mono_type (type);
token = mono_metadata_token_from_dor (
- mono_dynimage_encode_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
+ mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
} else if (strcmp (klass->name, "MonoCMethod") == 0 ||
strcmp (klass->name, "MonoMethod") == 0) {
MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
else
token = mono_image_get_inflated_method_token (assembly, m->method);
} else if ((m->method->klass->image == &assembly->image) &&
- !m->method->klass->generic_class) {
+ !mono_class_is_ginst (m->method->klass)) {
static guint32 method_table_idx = 0xffffff;
if (m->method->klass->wastypebuilder) {
/* we use the same token as the one that was assigned
MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)(gparam->tbuilder), error);
mono_error_assert_ok (error);
MonoClass *owner = mono_class_from_mono_type (type);
- g_assert (owner->generic_container);
- param->param.owner = owner->generic_container;
+ g_assert (mono_class_is_gtd (owner));
+ param->param.owner = mono_class_get_generic_container (owner);
}
pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
return TRUE;
}
- klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
+ /*
+ * The size calculation here warrants some explaining.
+ * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
+ * meaning we need to alloc enough space to morth a def into a gtd.
+ */
+ klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
+ klass->class_kind = MONO_CLASS_DEF;
klass->image = &tb->module->dynamic_image->image;
if (!is_ok (error))
goto failure;
klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
- klass->flags = tb->attrs;
+ mono_class_set_flags (klass, tb->attrs);
mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
if (count == 0)
return TRUE;
- klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
+ MonoGenericContainer *generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
+
+ generic_container->owner.klass = klass;
+ generic_container->type_argc = count;
+ generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
- klass->generic_container->owner.klass = klass;
- klass->generic_container->type_argc = count;
- klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
+ klass->class_kind = MONO_CLASS_GTD;
+ mono_class_set_generic_container (klass, generic_container);
- klass->is_generic = 1;
for (i = 0; i < count; i++) {
MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
return_val_if_nok (error, FALSE);
MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
- klass->generic_container->type_params [i] = *param;
+ generic_container->type_params [i] = *param;
/*Make sure we are a diferent type instance */
- klass->generic_container->type_params [i].param.owner = klass->generic_container;
- klass->generic_container->type_params [i].info.pklass = NULL;
- klass->generic_container->type_params [i].info.flags = gparam->attrs;
+ generic_container->type_params [i].param.owner = generic_container;
+ generic_container->type_params [i].info.pklass = NULL;
+ generic_container->type_params [i].info.flags = gparam->attrs;
- g_assert (klass->generic_container->type_params [i].param.owner);
+ g_assert (generic_container->type_params [i].param.owner);
}
- klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
+ generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
return TRUE;
}
image = dynamic ? NULL : klass->image;
if (!dynamic)
- g_assert (!klass->generic_class);
+ g_assert (!mono_class_is_ginst (klass));
mono_loader_lock ();
}
}
- if (klass->generic_container) {
- container->parent = klass->generic_container;
- container->context.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_gtd (klass)) {
+ container->parent = mono_class_get_generic_container (klass);
+ container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
}
container->context.method_inst = mono_get_shared_generic_inst (container);
}
static gboolean
fix_partial_generic_class (MonoClass *klass, MonoError *error)
{
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
int i;
mono_error_init (error);
return TRUE;
if (klass->parent != gklass->parent) {
- MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
+ MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &mono_class_get_generic_class (klass)->context, error);
if (mono_error_ok (error)) {
MonoClass *parent = mono_class_from_mono_type (parent_type);
mono_metadata_free_type (parent_type);
}
}
- if (!klass->generic_class->need_sync)
+ if (!mono_class_get_generic_class (klass)->need_sync)
return TRUE;
if (klass->method.count != gklass->method.count) {
static gboolean
ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
{
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_error_init (error);
mono_error_init (error);
- if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
+ if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
return TRUE;
if (klass->parent)
if (!ensure_runtime_vtable (klass->parent, error))
}
klass->interfaces_inited = 1;
}
- } else if (klass->generic_class){
+ } else if (mono_class_is_ginst (klass)){
if (!ensure_generic_class_runtime_vtable (klass, error)) {
mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
return FALSE;
}
}
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
int slot_num = 0;
for (i = 0; i < klass->method.count; ++i) {
MonoMethod *im = klass->methods [i];
}
klass->field.count = tb->num_fields;
- klass->field.first = 0;
mono_error_init (error);
MonoArray *rva_data;
fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
field = &klass->fields [i];
+ field->parent = klass;
field->name = mono_string_to_utf8_image (image, fb->name, error);
if (!mono_error_ok (error))
return;
}
if (fb->offset != -1)
field->offset = fb->offset;
- field->parent = klass;
fb->handle = field;
mono_save_custom_attrs (klass->image, field, fb->cattrs);
* Fields to set in klass:
* the various flags: delegate/unicode/contextbound etc.
*/
- klass->flags = tb->attrs;
+ mono_class_set_flags (klass, tb->attrs);
klass->has_cctor = 1;
mono_class_setup_parent (klass, klass->parent);
*
* Together with this we must ensure the contents of all instances to match the created type.
*/
- if (domain->type_hash && klass->generic_container) {
+ if (domain->type_hash && mono_class_is_gtd (klass)) {
struct remove_instantiations_user_data data;
data.klass = klass;
data.error = &error;
//g_assert (klass->wastypebuilder);
}
- if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
int i;
for (i = 0; i < inst->type_argc; ++i) {
static ThreadPoolDomain *
domain_get (MonoDomain *domain, gboolean create)
{
- ThreadPoolDomain *tpdomain = NULL;
guint i;
g_assert (domain);
for (i = 0; i < threadpool->domains->len; ++i) {
+ ThreadPoolDomain *tpdomain;
+
tpdomain = (ThreadPoolDomain *)g_ptr_array_index (threadpool->domains, i);
if (tpdomain->domain == domain)
return tpdomain;
}
if (create) {
+ ThreadPoolDomain *tpdomain;
ThreadPoolDomainCleanupSemaphore *cleanup_semaphore;
cleanup_semaphore = g_new0 (ThreadPoolDomainCleanupSemaphore, 1);
cleanup_semaphore->ref = 2;
tpdomain = g_new0 (ThreadPoolDomain, 1);
tpdomain->domain = domain;
domain_add (tpdomain);
+
+ return tpdomain;
}
- return tpdomain;
+ return NULL;
}
static void
void ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThread *this_obj);
HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this_obj, MonoObject *start);
-void ves_icall_System_Threading_InternalThread_Thread_free_internal(MonoInternalThread *this_obj, HANDLE thread);
+void ves_icall_System_Threading_InternalThread_Thread_free_internal(MonoInternalThread *this_obj);
void ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms);
gboolean ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms);
gint32 ves_icall_System_Threading_Thread_GetDomainID (void);
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/mono-error-internals.h>
-#include <mono/utils/w32handle.h>
+#include <mono/utils/os-event.h>
+#include <mono/utils/mono-threads-debug.h>
+#include <mono/metadata/w32handle.h>
#include <mono/metadata/w32event.h>
#include <mono/metadata/w32mutex.h>
static gint32 thread_interruption_requested = 0;
/* Event signaled when a thread changes its background mode */
-static HANDLE background_change_event;
+static MonoOSEvent background_change_event;
static gboolean shutting_down = FALSE;
}
static MonoThread*
-create_thread_object (MonoDomain *domain)
+create_thread_object (MonoDomain *domain, MonoInternalThread *internal)
{
+ MonoThread *thread;
+ MonoVTable *vtable;
MonoError error;
- MonoVTable *vt = mono_class_vtable (domain, mono_defaults.thread_class);
- MonoThread *t = (MonoThread*)mono_object_new_mature (vt, &error);
- /* only possible failure mode is OOM, from which we don't expect to recover. */
- mono_error_assert_ok (&error);
- return t;
-}
-static MonoThread*
-new_thread_with_internal (MonoDomain *domain, MonoInternalThread *internal)
-{
- MonoThread *thread;
+ vtable = mono_class_vtable (domain, mono_defaults.thread_class);
+ g_assert (vtable);
- thread = create_thread_object (domain);
+ thread = (MonoThread*)mono_object_new_mature (vtable, &error);
+ /* only possible failure mode is OOM, from which we don't expect to recover. */
+ mono_error_assert_ok (&error);
MONO_OBJECT_SETREF (thread, internal_thread, internal);
}
static MonoInternalThread*
-create_internal_thread (void)
+create_internal_thread_object (void)
{
MonoError error;
MonoInternalThread *thread;
thread->priority = MONO_THREAD_PRIORITY_NORMAL;
+ thread->suspended = g_new0 (MonoOSEvent, 1);
+ mono_os_event_init (thread->suspended, TRUE, TRUE);
+
return thread;
}
mono_thread_internal_set_priority (MonoInternalThread *internal, MonoThreadPriority priority)
{
g_assert (internal);
- g_assert (internal->handle);
g_assert (priority >= MONO_THREAD_PRIORITY_LOWEST);
g_assert (priority <= MONO_THREAD_PRIORITY_HIGHEST);
#ifdef HOST_WIN32
BOOL res;
- res = SetThreadPriority (internal->handle, priority - 2);
+ g_assert (internal->native_handle);
+
+ res = SetThreadPriority (internal->native_handle, priority - 2);
if (!res)
g_error ("%s: SetThreadPriority failed, error %d", __func__, GetLastError ());
#else /* HOST_WIN32 */
info = mono_thread_info_current ();
internal = thread->internal_thread;
- internal->handle = mono_thread_info_duplicate_handle (info);
+ internal->handle = mono_threads_open_thread_handle (info->handle);
+#ifdef HOST_WIN32
+ internal->native_handle = OpenThread (THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId ());
+#endif
internal->tid = MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ());
internal->thread_info = info;
internal->small_id = info->small_id;
g_assert (!internal->root_domain_thread);
if (domain != root_domain)
- MONO_OBJECT_SETREF (internal, root_domain_thread, new_thread_with_internal (root_domain, internal));
+ MONO_OBJECT_SETREF (internal, root_domain_thread, create_thread_object (root_domain, internal));
else
MONO_OBJECT_SETREF (internal, root_domain_thread, thread);
{
volatile gsize dummy;
- /* Avoid scanning the frames above this frame during a GC */
- mono_gc_set_stack_end ((void*)&dummy);
-
return start_wrapper_internal ((StartInfo*) data, (gsize*) &dummy);
}
gboolean threadpool_thread, guint32 stack_size, MonoError *error)
{
StartInfo *start_info = NULL;
- HANDLE thread_handle;
+ MonoThreadHandle *thread_handle;
MonoNativeThreadId tid;
gboolean ret;
gsize stack_set_size;
mono_error_init (error);
- thread = create_thread_object (domain);
+ internal = create_internal_thread_object ();
- internal = create_internal_thread ();
-
- MONO_OBJECT_SETREF (thread, internal_thread, internal);
+ thread = create_thread_object (domain, internal);
LOCK_THREAD (internal);
tid=mono_native_thread_id_get ();
- internal = create_internal_thread ();
+ internal = create_internal_thread_object ();
- thread = new_thread_with_internal (domain, internal);
+ thread = create_thread_object (domain, internal);
if (!mono_thread_attach_internal (thread, force_attach, TRUE, &stack_ptr)) {
/* Mono is shutting down, so just wait for the end */
if (mono_thread_get_main () && (thread == mono_thread_get_main ()->internal_thread))
exit (mono_environment_exitcode_get ());
- mono_thread_info_exit ();
+ mono_thread_info_exit (0);
}
void
{
MonoInternalThread *internal;
- internal = create_internal_thread ();
+ internal = create_internal_thread_object ();
internal->state = ThreadState_Unstarted;
* This is called from the finalizer of the internal thread object.
*/
void
-ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this_obj, HANDLE thread)
+ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this_obj)
{
- THREAD_DEBUG (g_message ("%s: Closing thread %p, handle %p", __func__, this, thread));
+ THREAD_DEBUG (g_message ("%s: Closing thread %p, handle %p", __func__, this, this_obj->handle));
/*
* Since threads keep a reference to their thread object while running, by the time this function is called,
* the thread has already exited/detached, i.e. thread_cleanup () has ran. The exception is during shutdown,
* when thread_cleanup () can be called after this.
*/
- if (thread)
- mono_threads_close_thread_handle (thread);
+ if (this_obj->handle) {
+ mono_threads_close_thread_handle (this_obj->handle);
+ this_obj->handle = NULL;
+ }
+
+#if HOST_WIN32
+ CloseHandle (this_obj->native_handle);
+#endif
if (this_obj->synch_cs) {
MonoCoopMutex *synch_cs = this_obj->synch_cs;
this_obj->name = NULL;
g_free (name);
}
+
+ g_assert (this_obj->suspended);
+ mono_os_event_destroy (this_obj->suspended);
+ g_free (this_obj->suspended);
+ this_obj->suspended = NULL;
}
void
LOCK_THREAD (internal);
internal->priority = priority;
- if (internal->handle != NULL)
+ if (internal->thread_info != NULL)
mono_thread_internal_set_priority (internal, priority);
UNLOCK_THREAD (internal);
}
if (!*current_thread_ptr) {
g_assert (domain != mono_get_root_domain ());
- *current_thread_ptr = new_thread_with_internal (domain, internal);
+ *current_thread_ptr = create_thread_object (domain, internal);
}
return *current_thread_ptr;
}
if (!*current_thread_ptr) {
g_assert (domain != mono_get_root_domain ());
- *current_thread_ptr = new_thread_with_internal (domain, internal);
+ *current_thread_ptr = create_thread_object (domain, internal);
}
return *current_thread_ptr;
}
ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms)
{
MonoInternalThread *thread = this_obj->internal_thread;
- HANDLE handle = thread->handle;
+ MonoThreadHandle *handle = thread->handle;
MonoInternalThread *cur_thread = mono_thread_internal_current ();
gboolean ret;
mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin);
MONO_ENTER_GC_SAFE;
- ret=WaitForSingleObjectEx (handle, ms, TRUE);
+ ret=mono_thread_info_wait_one_handle (handle, ms, TRUE);
MONO_EXIT_GC_SAFE;
mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin);
- if(ret==WAIT_OBJECT_0) {
+ if(ret==MONO_THREAD_INFO_WAIT_RET_SUCCESS_0) {
THREAD_DEBUG (g_message ("%s: join successful", __func__));
return(TRUE);
* be notified, since it has to rebuild the list of threads to
* wait for.
*/
- mono_w32event_set (background_change_event);
+ mono_os_event_set (&background_change_event);
}
}
* be notified, since it has to rebuild the list of threads to
* wait for.
*/
- mono_w32event_set (background_change_event);
+ mono_os_event_set (&background_change_event);
}
}
}
thread->state |= ThreadState_SuspendRequested;
+ if (mono_threads_is_coop_enabled ())
+ mono_os_event_reset (thread->suspended);
if (thread == mono_thread_internal_current ()) {
/* calls UNLOCK_THREAD (thread) */
mono_thread_resume (MonoInternalThread *thread)
{
if ((thread->state & ThreadState_SuspendRequested) != 0) {
+ // MOSTLY_ASYNC_SAFE_PRINTF ("RESUME (1) thread %p\n", thread_get_tid (thread));
+ if (mono_threads_is_coop_enabled ())
+ mono_os_event_set (thread->suspended);
thread->state &= ~ThreadState_SuspendRequested;
return TRUE;
}
(thread->state & ThreadState_Aborted) != 0 ||
(thread->state & ThreadState_Stopped) != 0)
{
+ // MOSTLY_ASYNC_SAFE_PRINTF ("RESUME (2) thread %p\n", thread_get_tid (thread));
return FALSE;
}
- UNLOCK_THREAD (thread);
+ // MOSTLY_ASYNC_SAFE_PRINTF ("RESUME (3) thread %p\n", thread_get_tid (thread));
- /* Awake the thread */
- if (!mono_thread_info_resume (thread_get_tid (thread)))
- return FALSE;
+ if (mono_threads_is_coop_enabled ()) {
+ mono_os_event_set (thread->suspended);
+ } else {
+ UNLOCK_THREAD (thread);
- LOCK_THREAD (thread);
+ /* Awake the thread */
+ if (!mono_thread_info_resume (thread_get_tid (thread)))
+ return FALSE;
+
+ LOCK_THREAD (thread);
+ }
thread->state &= ~ThreadState_Suspended;
mono_os_mutex_init_recursive(&interlocked_mutex);
mono_os_mutex_init_recursive(&joinable_threads_mutex);
- background_change_event = mono_w32event_create (TRUE, FALSE);
- g_assert(background_change_event != NULL);
+ mono_os_event_init (&background_change_event, TRUE, FALSE);
mono_init_static_data_info (&thread_static_info);
mono_init_static_data_info (&context_static_info);
mono_thread_start_cb = start_cb;
mono_thread_attach_cb = attach_cb;
-
- /* Get a pseudo handle to the current process. This is just a
- * kludge so that wapi can build a process handle if needed.
- * As a pseudo handle is returned, we don't need to clean
- * anything up.
- */
- GetCurrentProcess ();
}
void mono_thread_cleanup (void)
{
-#if !defined(RUN_IN_SUBTHREAD)
+#if !defined(RUN_IN_SUBTHREAD) && !defined(HOST_WIN32)
/* The main thread must abandon any held mutexes (particularly
* important for named mutexes as they are shared across
* processes, see bug 74680.) This will happen when the
* thread exits, but if it's not running in a subthread it
* won't exit in time.
*/
- mono_thread_info_set_exited (mono_thread_info_current ());
+ mono_w32mutex_abandon ();
#endif
#if 0
mono_os_mutex_destroy (&interlocked_mutex);
mono_os_mutex_destroy (&delayed_free_table_mutex);
mono_os_mutex_destroy (&small_id_mutex);
- CloseHandle (background_change_event);
+ mono_os_event_destroy (&background_change_event);
#endif
mono_native_tls_free (current_object_key);
struct wait_data
{
- HANDLE handles[MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
+ MonoThreadHandle *handles[MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
MonoInternalThread *threads[MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
guint32 num;
};
static void
wait_for_tids (struct wait_data *wait, guint32 timeout)
{
- guint32 i, ret;
+ guint32 i;
+ MonoThreadInfoWaitRet ret;
THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
MONO_ENTER_GC_SAFE;
- ret=WaitForMultipleObjectsEx(wait->num, wait->handles, TRUE, timeout, TRUE);
+ ret = mono_thread_info_wait_multiple_handle(wait->handles, wait->num, NULL, TRUE, timeout, TRUE);
MONO_EXIT_GC_SAFE;
- if(ret==WAIT_FAILED) {
+ if(ret==MONO_THREAD_INFO_WAIT_RET_FAILED) {
/* See the comment in build_wait_tids() */
THREAD_DEBUG (g_message ("%s: Wait failed", __func__));
return;
for(i=0; i<wait->num; i++)
mono_threads_close_thread_handle (wait->handles [i]);
- if (ret == WAIT_TIMEOUT)
+ if (ret == MONO_THREAD_INFO_WAIT_RET_TIMEOUT)
return;
for(i=0; i<wait->num; i++) {
static void wait_for_tids_or_state_change (struct wait_data *wait, guint32 timeout)
{
- guint32 i, ret, count;
+ guint32 i;
+ MonoThreadInfoWaitRet ret;
THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
- /* Add the thread state change event, so it wakes up if a thread changes
- * to background mode.
- */
- count = wait->num;
- if (count < MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
- wait->handles [count] = background_change_event;
- count++;
- }
+ /* Add the thread state change event, so it wakes
+ * up if a thread changes to background mode. */
MONO_ENTER_GC_SAFE;
- ret=WaitForMultipleObjectsEx (count, wait->handles, FALSE, timeout, TRUE);
+ ret = mono_thread_info_wait_multiple_handle (wait->handles, wait->num, &background_change_event, FALSE, timeout, TRUE);
MONO_EXIT_GC_SAFE;
- if(ret==WAIT_FAILED) {
+ if(ret==MONO_THREAD_INFO_WAIT_RET_FAILED) {
/* See the comment in build_wait_tids() */
THREAD_DEBUG (g_message ("%s: Wait failed", __func__));
return;
for(i=0; i<wait->num; i++)
mono_threads_close_thread_handle (wait->handles [i]);
- if (ret == WAIT_TIMEOUT)
+ if (ret == MONO_THREAD_INFO_WAIT_RET_TIMEOUT)
return;
if (ret < wait->num) {
{
struct wait_data *wait=(struct wait_data *)user;
- if(wait->num<MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
- HANDLE handle;
+ if(wait->num<MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS - 1) {
MonoInternalThread *thread=(MonoInternalThread *)value;
/* Ignore background threads, we abort them later */
return;
}
- handle = mono_threads_open_thread_handle (thread->handle, thread_get_tid (thread));
- if (handle == NULL) {
- THREAD_DEBUG (g_message ("%s: ignoring unopenable thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
- return;
- }
-
THREAD_DEBUG (g_message ("%s: Invoking mono_thread_manage callback on thread %p", __func__, thread));
if ((thread->manage_callback == NULL) || (thread->manage_callback (thread->root_domain_thread) == TRUE)) {
- wait->handles[wait->num]=handle;
+ wait->handles[wait->num]=mono_threads_open_thread_handle (thread->handle);
wait->threads[wait->num]=thread;
wait->num++;
struct wait_data *wait=(struct wait_data *)user;
MonoNativeThreadId self = mono_native_thread_id_get ();
MonoInternalThread *thread = (MonoInternalThread *)value;
- HANDLE handle;
if (wait->num >= MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS)
return FALSE;
&& (thread->state & ThreadState_Background) != 0
&& (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE) == 0
) {
- handle = mono_threads_open_thread_handle (thread->handle, thread_get_tid (thread));
- if (handle == NULL)
- return FALSE;
-
- wait->handles[wait->num] = handle;
+ wait->handles[wait->num] = mono_threads_open_thread_handle (thread->handle);
wait->threads[wait->num] = thread;
wait->num++;
mono_thread_detach_internal (current_thread);
/* Wake up other threads potentially waiting for us */
- mono_thread_info_exit ();
+ mono_thread_info_exit (0);
} else {
shutting_down = TRUE;
* interrupt the main thread if it is waiting for all
* the other threads.
*/
- mono_w32event_set (background_change_event);
+ mono_os_event_set (&background_change_event);
mono_threads_unlock ();
}
THREAD_DEBUG (g_message ("%s: There are %d threads to join", __func__, mono_g_hash_table_size (threads));
mono_g_hash_table_foreach (threads, print_tids, NULL));
- mono_w32event_reset (background_change_event);
+ mono_os_event_reset (&background_change_event);
wait->num=0;
/*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
memset (wait->threads, 0, MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
{
MonoInternalThread *thread = (MonoInternalThread*)value;
struct wait_data *wait = (struct wait_data*)user_data;
- HANDLE handle;
/*
* We try to exclude threads early, to avoid running into the MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS
return;
if (wait->num<MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
- handle = mono_threads_open_thread_handle (thread->handle, thread_get_tid (thread));
- if (handle == NULL)
- return;
-
- wait->handles [wait->num] = handle;
+ wait->handles [wait->num] = mono_threads_open_thread_handle (thread->handle);
wait->threads [wait->num] = thread;
wait->num++;
}
thread->state &= ~ThreadState_AbortRequested;
thread->state |= ThreadState_SuspendRequested;
+ if (mono_threads_is_coop_enabled ())
+ mono_os_event_reset (thread->suspended);
/* Signal the thread to suspend + calls UNLOCK_THREAD (thread) */
async_suspend_internal (thread, TRUE);
/* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread->tid, domain->friendly_name); */
if(data->wait.num<MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
- HANDLE handle = mono_threads_open_thread_handle (thread->handle, thread_get_tid (thread));
- if (handle == NULL)
- return;
- data->wait.handles [data->wait.num] = handle;
+ data->wait.handles [data->wait.num] = mono_threads_open_thread_handle (thread->handle);
data->wait.threads [data->wait.num] = thread;
data->wait.num++;
} else {
or similar */
/* Our implementation of this function ignores the func argument */
#ifdef HOST_WIN32
- QueueUserAPC ((PAPCFUNC)dummy_apc, thread->handle, (ULONG_PTR)NULL);
+ QueueUserAPC ((PAPCFUNC)dummy_apc, thread->native_handle, (ULONG_PTR)NULL);
#else
mono_thread_info_self_interrupt ();
#endif
static void
self_interrupt_thread (void *_unused)
{
- MonoThreadInfo *info = mono_thread_info_current ();
- MonoException *exc = mono_thread_execute_interruption ();
- if (exc) /*We must use _with_context since we didn't trampoline into the runtime*/
- mono_raise_exception_with_context (exc, &info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx); /* FIXME using thread_saved_state [ASYNC_SUSPEND_STATE_INDEX] can race with another suspend coming in. */
- g_assert_not_reached (); /*this MUST not happen since we can't resume from an async call*/
+ MonoException *exc;
+ MonoThreadInfo *info;
+
+ exc = mono_thread_execute_interruption ();
+ if (!exc) {
+ if (mono_threads_is_coop_enabled ()) {
+ /* We can return from an async call in coop, as
+ * it's simply called when exiting the safepoint */
+ return;
+ }
+
+ g_error ("%s: we can't resume from an async call", __func__);
+ }
+
+ info = mono_thread_info_current ();
+
+ /* We must use _with_context since we didn't trampoline into the runtime */
+ mono_raise_exception_with_context (exc, &info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx); /* FIXME using thread_saved_state [ASYNC_SUSPEND_STATE_INDEX] can race with another suspend coming in. */
}
static gboolean
running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx));
if (running_managed && !protected_wrapper) {
- thread->state &= ~ThreadState_SuspendRequested;
- thread->state |= ThreadState_Suspended;
- return KeepSuspended;
+ if (mono_threads_is_coop_enabled ()) {
+ mono_thread_info_setup_async_call (info, self_interrupt_thread, NULL);
+ return MonoResumeThread;
+ } else {
+ thread->state &= ~ThreadState_SuspendRequested;
+ thread->state |= ThreadState_Suspended;
+ return KeepSuspended;
+ }
} else {
if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0)
InterlockedIncrement (&thread_interruption_requested);
g_assert (thread != mono_thread_internal_current ());
+ // MOSTLY_ASYNC_SAFE_PRINTF ("ASYNC SUSPEND thread %p\n", thread_get_tid (thread));
+
data.thread = thread;
data.interrupt = interrupt;
data.interrupt_token = NULL;
thread = mono_thread_internal_current ();
- mono_thread_info_begin_self_suspend ();
+ // MOSTLY_ASYNC_SAFE_PRINTF ("SELF SUSPEND thread %p\n", thread_get_tid (thread));
+
+ if (!mono_threads_is_coop_enabled ())
+ mono_thread_info_begin_self_suspend ();
+
thread->state &= ~ThreadState_SuspendRequested;
thread->state |= ThreadState_Suspended;
UNLOCK_THREAD (thread);
- mono_thread_info_end_self_suspend ();
+ if (!mono_threads_is_coop_enabled ())
+ mono_thread_info_end_self_suspend ();
+ else {
+ MonoOSEvent *event;
+ MonoOSEventWaitRet res;
+
+ event = thread->suspended;
+
+ MONO_ENTER_GC_SAFE;
+ res = mono_os_event_wait_one (event, MONO_INFINITE_WAIT);
+ g_assert (res == MONO_OS_EVENT_WAIT_RET_SUCCESS_0);
+ MONO_EXIT_GC_SAFE;
+ }
}
/*
if (klass->byval_arg.type != type->type)
return mono_type_is_valid_type_in_context_full (&klass->byval_arg, context, check_gtd);
- if (check_gtd && klass->generic_container)
+ if (check_gtd && mono_class_is_gtd (klass))
return FALSE;
break;
}
* The type A <K> has a parent B<K>, that is inflated into the GTD B<>.
* Since A<K> is open, thus not instantiatable, this is valid.
*/
- if (paramClass->generic_container && param_type->type != MONO_TYPE_GENERICINST && !ginst->is_open)
+ if (mono_class_is_gtd (paramClass) && param_type->type != MONO_TYPE_GENERICINST && !ginst->is_open)
return FALSE;
/*it's not safe to call mono_class_init from here*/
- if (paramClass->generic_class && !paramClass->inited) {
+ if (mono_class_is_ginst (paramClass) && !paramClass->inited) {
if (!mono_class_is_valid_generic_instantiation (NULL, paramClass))
return FALSE;
}
if (type->type == MONO_TYPE_VAR) {
MonoClass *gtd = method->klass;
- if (gtd->generic_class)
- gtd = gtd->generic_class->container_class;
- gc = gtd->generic_container;
+ if (mono_class_is_ginst (gtd))
+ gtd = mono_class_get_generic_class (gtd)->container_class;
+ gc = mono_class_try_get_generic_container (gtd);
} else { //MVAR
MonoMethod *gmd = method;
if (method->is_inflated)
static gboolean
mono_class_repect_method_constraints (VerifyContext *ctx, MonoClass *klass)
{
- MonoGenericClass *gklass = klass->generic_class;
+ MonoGenericClass *gklass = mono_class_get_generic_class (klass);
MonoGenericInst *ginst = gklass->context.class_inst;
- MonoGenericContainer *gc = gklass->container_class->generic_container;
+ MonoGenericContainer *gc = mono_class_get_generic_container (gklass->container_class);
return !gc || generic_arguments_respect_constraints (ctx, gc, &gklass->context, ginst);
}
static gboolean
mono_class_is_valid_generic_instantiation (VerifyContext *ctx, MonoClass *klass)
{
- MonoGenericClass *gklass = klass->generic_class;
+ MonoGenericClass *gklass = mono_class_get_generic_class (klass);
MonoGenericInst *ginst = gklass->context.class_inst;
- MonoGenericContainer *gc = gklass->container_class->generic_container;
+ MonoGenericContainer *gc = mono_class_get_generic_container (gklass->container_class);
if (ctx && !is_valid_generic_instantiation_in_context (ctx, ginst, TRUE))
return FALSE;
return is_valid_generic_instantiation (gc, &gklass->context, ginst);
klass = mono_class_from_mono_type (type);
mono_class_init (klass);
if (mono_class_has_failure (klass)) {
- if (klass->generic_class && !mono_class_is_valid_generic_instantiation (NULL, klass))
+ if (mono_class_is_ginst (klass) && !mono_class_is_valid_generic_instantiation (NULL, klass))
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic instantiation of type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
else
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
return FALSE;
}
- if (klass->generic_class && mono_class_has_failure (klass->generic_class->container_class)) {
+ if (mono_class_is_ginst (klass) && mono_class_has_failure (mono_class_get_generic_class (klass)->container_class)) {
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
return FALSE;
}
- if (!klass->generic_class)
+ if (!mono_class_is_ginst (klass))
return TRUE;
if (!mono_class_is_valid_generic_instantiation (ctx, klass)) {
if (!(klass = mono_class_from_mono_type (type)))
ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not retrieve type token for %s at 0x%04x", opcode, ctx->ip_offset));
- if (klass->generic_container && type->type != MONO_TYPE_GENERICINST)
+ if (mono_class_is_gtd (klass) && type->type != MONO_TYPE_GENERICINST)
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use the generic type definition in a boxable type position for %s at 0x%04x", opcode, ctx->ip_offset));
check_unverifiable_type (ctx, type);
if (mono_class_is_assignable_from (target, candidate))
return TRUE;
- if (!MONO_CLASS_IS_INTERFACE (target) || !target->generic_class || candidate->rank != 1)
+ if (!MONO_CLASS_IS_INTERFACE (target) || !mono_class_is_ginst (target) || candidate->rank != 1)
return FALSE;
- iface_gtd = target->generic_class->container_class;
+ iface_gtd = mono_class_get_generic_class (target)->container_class;
if (iface_gtd != mono_defaults.generic_ilist_class && iface_gtd != get_icollection_class () && iface_gtd != get_ienumerable_class ())
return FALSE;
- target = mono_class_from_mono_type (target->generic_class->context.class_inst->type_argv [0]);
+ target = mono_class_from_mono_type (mono_class_get_generic_class (target)->context.class_inst->type_argv [0]);
candidate = candidate->element_class;
return TRUE;
* the object is a this arg (comes from a ldarg.0), and there is no starg.0.
* This rules doesn't apply if the object on stack is a boxed valuetype.
*/
- if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED) && !stack_slot_is_boxed_value (value)) {
+ if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !mono_class_is_sealed (method->klass) && !stack_slot_is_boxed_value (value)) {
/*A stdarg 0 must not happen, we fail here only in fail fast mode to avoid double error reports*/
if (IS_FAIL_FAST_MODE (ctx) && ctx->has_this_store)
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid ldftn with virtual function in method with stdarg 0 at 0x%04x", ctx->ip_offset));
if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use call with an abstract method at 0x%04x", ctx->ip_offset));
- if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+ if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !mono_class_is_sealed (method->klass)) {
virt_check_this = TRUE;
ctx->code [ctx->ip_offset].flags |= IL_CODE_CALL_NONFINAL_VIRTUAL;
}
return;
}
- if (method->klass->flags & (TYPE_ATTRIBUTE_ABSTRACT | TYPE_ATTRIBUTE_INTERFACE))
+ if (mono_class_get_flags (method->klass) & (TYPE_ATTRIBUTE_ABSTRACT | TYPE_ATTRIBUTE_INTERFACE))
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Trying to instantiate an abstract or interface type at 0x%04x", ctx->ip_offset));
if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, NULL)) {
}
/* if old class is an interface that new class implements */
- if (old_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (old_class)) {
if (verifier_class_is_assignable_from (old_class, new_class)) {
match_class = old_class;
goto match_found;
}
}
- if (new_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (new_class)) {
if (verifier_class_is_assignable_from (new_class, old_class)) {
match_class = new_class;
goto match_found;
finish_collect_stats ();
return ctx.list;
}
- if (!method->is_generic && !method->klass->is_generic && ctx.signature->has_type_parameters) {
+ if (!method->is_generic && !mono_class_is_gtd (method->klass) && ctx.signature->has_type_parameters) {
ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Method and signature don't match in terms of genericity"));
finish_collect_stats ();
return ctx.list;
if (ctx.signature->is_inflated)
ctx.generic_context = generic_context = mono_method_get_context (method);
- if (!generic_context && (method->klass->generic_container || method->is_generic)) {
+ if (!generic_context && (mono_class_is_gtd (method->klass) || method->is_generic)) {
if (method->is_generic)
ctx.generic_context = generic_context = &(mono_method_get_generic_container (method)->context);
else
- ctx.generic_context = generic_context = &method->klass->generic_container->context;
+ ctx.generic_context = generic_context = &mono_class_get_generic_container (method->klass)->context;
}
for (i = 0; i < ctx.num_locals; ++i) {
MonoClassField *field;
gboolean is_fulltrust = mono_verifier_is_class_full_trust (klass);
/*We can't skip types with !has_references since this is calculated after we have run.*/
- if (!((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT))
+ if (!mono_class_is_explicit_layout (klass))
return TRUE;
MonoClassField *field;
MonoGenericContext *context = mono_class_get_context (klass);
GHashTable *unique_fields = g_hash_table_new_full (&field_hash, &field_equals, NULL, NULL);
- if (klass->generic_container)
- context = &klass->generic_container->context;
+ if (mono_class_is_gtd (klass))
+ context = &mono_class_get_generic_container (klass)->context;
while ((field = mono_class_get_fields (klass, &iter)) != NULL) {
if (!mono_type_is_valid_type_in_context (field->type, context)) {
int i;
for (i = 0; i < klass->interface_count; ++i) {
MonoClass *iface = klass->interfaces [i];
- if (!(iface->flags & TYPE_ATTRIBUTE_INTERFACE))
+ if (!mono_class_get_flags (iface))
return FALSE;
}
return TRUE;
verify_generic_parameters (MonoClass *klass)
{
int i;
- MonoGenericContainer *gc = klass->generic_container;
+ MonoGenericContainer *gc = mono_class_get_generic_container (klass);
MonoBitSet *used_args = mono_bitset_new (gc->type_argc, 0);
for (i = 0; i < gc->type_argc; ++i) {
if (mono_type_is_generic_argument (constraint_type) && !recursive_mark_constraint_args (used_args, gc, constraint_type))
goto fail;
- if (ctr->generic_class && !mono_class_is_valid_generic_instantiation (NULL, ctr))
+ if (mono_class_is_ginst (ctr) && !mono_class_is_valid_generic_instantiation (NULL, ctr))
goto fail;
}
}
if (klass->parent) {
if (MONO_CLASS_IS_INTERFACE (klass->parent))
return FALSE;
- if (!klass->generic_class && klass->parent->generic_container)
+ if (!mono_class_is_ginst (klass) && mono_class_is_gtd (klass->parent))
return FALSE;
- if (klass->parent->generic_class && !klass->generic_class) {
+ if (mono_class_is_ginst (klass->parent) && !mono_class_is_ginst (klass)) {
MonoGenericContext *context = mono_class_get_context (klass);
- if (klass->generic_container)
- context = &klass->generic_container->context;
+ if (mono_class_is_gtd (klass))
+ context = &mono_class_get_generic_container (klass)->context;
if (!mono_type_is_valid_type_in_context (&klass->parent->byval_arg, context))
return FALSE;
}
}
- if (klass->generic_container && (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)
+ if (mono_class_is_gtd (klass) && (mono_class_is_explicit_layout (klass)))
return FALSE;
- if (klass->generic_container && !verify_generic_parameters (klass))
+ if (mono_class_is_gtd (klass) && !verify_generic_parameters (klass))
return FALSE;
if (!verify_class_for_overlapping_reference_fields (klass))
return FALSE;
- if (klass->generic_class && !mono_class_is_valid_generic_instantiation (NULL, klass))
+ if (mono_class_is_ginst (klass) && !mono_class_is_valid_generic_instantiation (NULL, klass))
return FALSE;
- if (klass->generic_class == NULL && !verify_class_fields (klass))
+ if (!mono_class_is_ginst (klass) && !verify_class_fields (klass))
return FALSE;
if (klass->valuetype && !verify_valuetype_layout (klass))
return FALSE;
#include "w32handle-namespace.h"
#include "mono/io-layer/io-layer.h"
#include "mono/utils/mono-logger-internals.h"
-#include "mono/utils/w32handle.h"
+#include "mono/metadata/w32handle.h"
typedef struct {
gboolean manual;
#include <config.h>
#include <glib.h>
-#include "mono/utils/w32handle.h"
+#include "mono/metadata/w32handle.h"
#define MONO_W32HANDLE_NAMESPACE_MAX_PATH 260
--- /dev/null
+/*
+ * w32handle.c: Generic and internal operations on handles
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * (C) 2002-2011 Novell, Inc.
+ * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#if !defined(HOST_WIN32)
+
+#include <glib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+#include <sys/stat.h>
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+#include "w32handle.h"
+
+#include "utils/atomic.h"
+#include "utils/mono-logger-internals.h"
+#include "utils/mono-os-mutex.h"
+#include "utils/mono-proclib.h"
+#include "utils/mono-threads.h"
+#include "utils/mono-time.h"
+
+#undef DEBUG_REFS
+
+#define SLOT_MAX (1024 * 16)
+
+/* must be a power of 2 */
+#define HANDLE_PER_SLOT (256)
+
+#define INFINITE 0xFFFFFFFF
+
+typedef struct {
+ MonoW32HandleType type;
+ guint ref;
+ gboolean signalled;
+ mono_mutex_t signal_mutex;
+ mono_cond_t signal_cond;
+ gpointer specific;
+} MonoW32HandleBase;
+
+static MonoW32HandleCapability handle_caps [MONO_W32HANDLE_COUNT];
+static MonoW32HandleOps *handle_ops [MONO_W32HANDLE_COUNT];
+
+/*
+ * We can hold SLOT_MAX * HANDLE_PER_SLOT handles.
+ * If 4M handles are not enough... Oh, well... we will crash.
+ */
+#define SLOT_INDEX(x) (x / HANDLE_PER_SLOT)
+#define SLOT_OFFSET(x) (x % HANDLE_PER_SLOT)
+
+static MonoW32HandleBase *private_handles [SLOT_MAX];
+static guint32 private_handles_count = 0;
+static guint32 private_handles_slots_count = 0;
+
+guint32 mono_w32handle_fd_reserve;
+
+/*
+ * This is an internal handle which is used for handling waiting for multiple handles.
+ * Threads which wait for multiple handles wait on this one handle, and when a handle
+ * is signalled, this handle is signalled too.
+ */
+static mono_mutex_t global_signal_mutex;
+static mono_cond_t global_signal_cond;
+
+static mono_mutex_t scan_mutex;
+
+static gboolean shutting_down = FALSE;
+
+static gboolean
+type_is_fd (MonoW32HandleType type)
+{
+ switch (type) {
+ case MONO_W32HANDLE_FILE:
+ case MONO_W32HANDLE_CONSOLE:
+ case MONO_W32HANDLE_SOCKET:
+ case MONO_W32HANDLE_PIPE:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static gboolean
+mono_w32handle_lookup_data (gpointer handle, MonoW32HandleBase **handle_data)
+{
+ gsize index, offset;
+
+ g_assert (handle_data);
+
+ index = SLOT_INDEX ((gsize) handle);
+ if (index >= SLOT_MAX)
+ return FALSE;
+ if (!private_handles [index])
+ return FALSE;
+
+ offset = SLOT_OFFSET ((gsize) handle);
+ if (private_handles [index][offset].type == MONO_W32HANDLE_UNUSED)
+ return FALSE;
+
+ *handle_data = &private_handles [index][offset];
+ return TRUE;
+}
+
+MonoW32HandleType
+mono_w32handle_get_type (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ return MONO_W32HANDLE_UNUSED; /* An impossible type */
+
+ return handle_data->type;
+}
+
+void
+mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+#ifdef DEBUG
+ g_message ("%s: setting state of %p to %s (broadcast %s)", __func__,
+ handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
+#endif
+
+ if (state == TRUE) {
+ /* Tell everyone blocking on a single handle */
+
+ /* The condition the global signal cond is waiting on is the signalling of
+ * _any_ handle. So lock it before setting the signalled state.
+ */
+ mono_os_mutex_lock (&global_signal_mutex);
+
+ /* This function _must_ be called with
+ * handle->signal_mutex locked
+ */
+ handle_data->signalled=state;
+
+ if (broadcast == TRUE) {
+ mono_os_cond_broadcast (&handle_data->signal_cond);
+ } else {
+ mono_os_cond_signal (&handle_data->signal_cond);
+ }
+
+ /* Tell everyone blocking on multiple handles that something
+ * was signalled
+ */
+ mono_os_cond_broadcast (&global_signal_cond);
+
+ mono_os_mutex_unlock (&global_signal_mutex);
+ } else {
+ handle_data->signalled=state;
+ }
+}
+
+gboolean
+mono_w32handle_issignalled (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ return handle_data->signalled;
+}
+
+static int
+mono_w32handle_lock_signal_mutex (void)
+{
+#ifdef DEBUG
+ g_message ("%s: lock global signal mutex", __func__);
+#endif
+
+ mono_os_mutex_lock (&global_signal_mutex);
+
+ return 0;
+}
+
+static int
+mono_w32handle_unlock_signal_mutex (void)
+{
+#ifdef DEBUG
+ g_message ("%s: unlock global signal mutex", __func__);
+#endif
+
+ mono_os_mutex_unlock (&global_signal_mutex);
+
+ return 0;
+}
+
+int
+mono_w32handle_lock_handle (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+#ifdef DEBUG
+ g_message ("%s: locking handle %p", __func__, handle);
+#endif
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(0);
+ }
+
+ mono_w32handle_ref (handle);
+
+ mono_os_mutex_lock (&handle_data->signal_mutex);
+
+ return 0;
+}
+
+int
+mono_w32handle_trylock_handle (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ int ret;
+
+#ifdef DEBUG
+ g_message ("%s: locking handle %p", __func__, handle);
+#endif
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(0);
+ }
+
+ mono_w32handle_ref (handle);
+
+ ret = mono_os_mutex_trylock (&handle_data->signal_mutex);
+ if (ret != 0) {
+ mono_w32handle_unref (handle);
+ }
+
+ return(ret);
+}
+
+int
+mono_w32handle_unlock_handle (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+#ifdef DEBUG
+ g_message ("%s: unlocking handle %p", __func__, handle);
+#endif
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(0);
+ }
+
+ mono_os_mutex_unlock (&handle_data->signal_mutex);
+
+ mono_w32handle_unref (handle);
+
+ return 0;
+}
+
+/*
+ * wapi_init:
+ *
+ * Initialize the io-layer.
+ */
+void
+mono_w32handle_init (void)
+{
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
+ == MONO_W32HANDLE_COUNT);
+
+ /* This is needed by the code in mono_w32handle_new_internal */
+ mono_w32handle_fd_reserve = (eg_getdtablesize () + (HANDLE_PER_SLOT - 1)) & ~(HANDLE_PER_SLOT - 1);
+
+ do {
+ /*
+ * The entries in private_handles reserved for fds are allocated lazily to
+ * save memory.
+ */
+
+ private_handles_count += HANDLE_PER_SLOT;
+ private_handles_slots_count ++;
+ } while(mono_w32handle_fd_reserve > private_handles_count);
+
+ mono_os_mutex_init (&scan_mutex);
+
+ mono_os_cond_init (&global_signal_cond);
+ mono_os_mutex_init (&global_signal_mutex);
+
+ initialized = TRUE;
+}
+
+void
+mono_w32handle_cleanup (void)
+{
+ int i, j, k;
+
+ g_assert (!shutting_down);
+ shutting_down = TRUE;
+
+ /* Every shared handle we were using ought really to be closed
+ * by now, but to make sure just blow them all away. The
+ * exiting finalizer thread in particular races us to the
+ * program exit and doesn't always win, so it can be left
+ * cluttering up the shared file. Anything else left over is
+ * really a bug.
+ */
+ for(i = SLOT_INDEX (0); private_handles[i] != NULL; i++) {
+ for(j = SLOT_OFFSET (0); j < HANDLE_PER_SLOT; j++) {
+ MonoW32HandleBase *handle_data = &private_handles[i][j];
+ gpointer handle = GINT_TO_POINTER (i*HANDLE_PER_SLOT+j);
+
+ for(k = handle_data->ref; k > 0; k--) {
+ mono_w32handle_unref (handle);
+ }
+ }
+ }
+
+ for (i = 0; i < SLOT_MAX; ++i)
+ g_free (private_handles [i]);
+}
+
+static void mono_w32handle_init_handle (MonoW32HandleBase *handle,
+ MonoW32HandleType type, gpointer handle_specific)
+{
+ g_assert (handle->ref == 0);
+
+ handle->type = type;
+ handle->signalled = FALSE;
+ handle->ref = 1;
+
+ 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));
+}
+
+/*
+ * mono_w32handle_new_internal:
+ * @type: Init handle to this type
+ *
+ * Search for a free handle and initialize it. Return the handle on
+ * success and 0 on failure. This is only called from
+ * mono_w32handle_new, and scan_mutex must be held.
+ */
+static guint32 mono_w32handle_new_internal (MonoW32HandleType type,
+ gpointer handle_specific)
+{
+ guint32 i, k, count;
+ static guint32 last = 0;
+ gboolean retry = FALSE;
+
+ /* A linear scan should be fast enough. Start from the last
+ * allocation, assuming that handles are allocated more often
+ * than they're freed. Leave the space reserved for file
+ * descriptors
+ */
+
+ if (last < mono_w32handle_fd_reserve) {
+ last = mono_w32handle_fd_reserve;
+ } else {
+ retry = TRUE;
+ }
+
+again:
+ count = last;
+ for(i = SLOT_INDEX (count); i < private_handles_slots_count; i++) {
+ if (private_handles [i]) {
+ for (k = SLOT_OFFSET (count); k < HANDLE_PER_SLOT; k++) {
+ MonoW32HandleBase *handle = &private_handles [i][k];
+
+ if(handle->type == MONO_W32HANDLE_UNUSED) {
+ last = count + 1;
+
+ mono_w32handle_init_handle (handle, type, handle_specific);
+ return (count);
+ }
+ count++;
+ }
+ }
+ }
+
+ if(retry && last > mono_w32handle_fd_reserve) {
+ /* Try again from the beginning */
+ last = mono_w32handle_fd_reserve;
+ goto again;
+ }
+
+ /* Will need to expand the array. The caller will sort it out */
+
+ return(0);
+}
+
+gpointer
+mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific)
+{
+ guint32 handle_idx = 0;
+ gpointer handle;
+
+ g_assert (!shutting_down);
+
+ g_assert(!type_is_fd(type));
+
+ 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 */
+ int idx = SLOT_INDEX (private_handles_count);
+ if (idx >= SLOT_MAX) {
+ break;
+ }
+
+ private_handles [idx] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+
+ private_handles_count += HANDLE_PER_SLOT;
+ private_handles_slots_count ++;
+ }
+
+ mono_os_mutex_unlock (&scan_mutex);
+
+ if (handle_idx == 0) {
+ /* We ran out of slots */
+ handle = INVALID_HANDLE_VALUE;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle", __func__, mono_w32handle_ops_typename (type));
+ goto done;
+ }
+
+ /* Make sure we left the space for fd mappings */
+ g_assert (handle_idx >= mono_w32handle_fd_reserve);
+
+ handle = GUINT_TO_POINTER (handle_idx);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
+
+done:
+ return(handle);
+}
+
+gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd,
+ gpointer handle_specific)
+{
+ MonoW32HandleBase *handle_data;
+ int fd_index, fd_offset;
+
+ g_assert (!shutting_down);
+
+ g_assert(type_is_fd(type));
+
+ if (fd >= mono_w32handle_fd_reserve) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is too big", __func__, mono_w32handle_ops_typename (type));
+
+ return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
+ }
+
+ fd_index = SLOT_INDEX (fd);
+ fd_offset = SLOT_OFFSET (fd);
+
+ /* Initialize the array entries on demand */
+ if (!private_handles [fd_index]) {
+ mono_os_mutex_lock (&scan_mutex);
+
+ if (!private_handles [fd_index])
+ private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+
+ mono_os_mutex_unlock (&scan_mutex);
+ }
+
+ handle_data = &private_handles [fd_index][fd_offset];
+
+ if (handle_data->type != MONO_W32HANDLE_UNUSED) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is already in use", __func__, mono_w32handle_ops_typename (type));
+ /* FIXME: clean up this handle? We can't do anything
+ * with the fd, cos thats the new one
+ */
+ return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), GUINT_TO_POINTER(fd));
+
+ mono_w32handle_init_handle (handle_data, type, handle_specific);
+
+ return(GUINT_TO_POINTER(fd));
+}
+
+gboolean
+mono_w32handle_lookup (gpointer handle, MonoW32HandleType type,
+ gpointer *handle_specific)
+{
+ MonoW32HandleBase *handle_data;
+
+ g_assert (handle_specific);
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ if (handle_data->type != type) {
+ return(FALSE);
+ }
+
+ *handle_specific = handle_data->specific;
+
+ return(TRUE);
+}
+
+static gboolean
+mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
+
+static gboolean
+mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data, guint minimum);
+
+void
+mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data)
+{
+ guint32 i, k;
+
+ mono_os_mutex_lock (&scan_mutex);
+
+ for (i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
+ if (!private_handles [i])
+ continue;
+ for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) {
+ MonoW32HandleBase *handle_data = NULL;
+ gpointer handle;
+ gboolean destroy, finished;
+
+ handle_data = &private_handles [i][k];
+ if (handle_data->type == MONO_W32HANDLE_UNUSED)
+ continue;
+
+ handle = GUINT_TO_POINTER (i * HANDLE_PER_SLOT + k);
+
+ if (!mono_w32handle_ref_core (handle, handle_data)) {
+ /* we are racing with mono_w32handle_unref:
+ * the handle ref has been decremented, but it
+ * hasn't yet been destroyed. */
+ continue;
+ }
+
+ finished = on_each (handle, handle_data->specific, user_data);
+
+ /* we do not want to have to destroy the handle here,
+ * as it would means the ref/unref are unbalanced */
+ destroy = mono_w32handle_unref_core (handle, handle_data, 2);
+ g_assert (!destroy);
+
+ if (finished)
+ goto done;
+ }
+ }
+
+done:
+ mono_os_mutex_unlock (&scan_mutex);
+}
+
+typedef struct {
+ MonoW32HandleType type;
+ gboolean (*search_user_callback)(gpointer handle, gpointer data);
+ gpointer search_user_data;
+ gpointer handle;
+ gpointer handle_specific;
+} SearchData;
+
+static gboolean
+search_callback (gpointer handle, gpointer handle_specific, gpointer user_data)
+{
+ SearchData *search_data = (SearchData*) user_data;
+
+ if (search_data->type != mono_w32handle_get_type (handle))
+ return FALSE;
+
+ if (!search_data->search_user_callback (handle, search_data->search_user_data))
+ return FALSE;
+
+ mono_w32handle_ref (handle);
+ search_data->handle = handle;
+ search_data->handle_specific = handle_specific;
+ return TRUE;
+}
+
+/* This might list some shared handles twice if they are already
+ * opened by this process, and the check function returns FALSE the
+ * first time. Shared handles that are created during the search are
+ * unreffed if the check function returns FALSE, so callers must not
+ * rely on the handle persisting (unless the check function returns
+ * TRUE)
+ * The caller owns the returned handle.
+ */
+gpointer mono_w32handle_search (MonoW32HandleType type,
+ gboolean (*check)(gpointer test, gpointer user),
+ gpointer user_data,
+ gpointer *handle_specific,
+ gboolean search_shared)
+{
+ SearchData search_data;
+
+ memset (&search_data, 0, sizeof (search_data));
+ search_data.type = type;
+ search_data.search_user_callback = check;
+ search_data.search_user_data = user_data;
+ mono_w32handle_foreach (search_callback, &search_data);
+ if (handle_specific)
+ *handle_specific = search_data.handle_specific;
+ return search_data.handle;
+}
+
+static gboolean
+mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data)
+{
+ guint old, new;
+
+ do {
+ old = handle_data->ref;
+ if (old == 0)
+ return FALSE;
+
+ new = old + 1;
+ } while (InterlockedCompareExchange ((gint32*) &handle_data->ref, new, old) != old);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: ref %s handle %p, ref: %d -> %d",
+ __func__, mono_w32handle_ops_typename (handle_data->type), handle, old, new);
+
+ return TRUE;
+}
+
+static gboolean
+mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data, guint minimum)
+{
+ MonoW32HandleType type;
+ guint old, new;
+
+ type = handle_data->type;
+
+ do {
+ old = handle_data->ref;
+ if (!(old >= minimum))
+ g_error ("%s: handle %p has ref %d, it should be >= %d", __func__, handle, old, minimum);
+
+ new = old - 1;
+ } while (InterlockedCompareExchange ((gint32*) &handle_data->ref, new, old) != old);
+
+ /* handle_data might contain invalid data from now on, if
+ * another thread is unref'ing this handle at the same time */
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: unref %s handle %p, ref: %d -> %d destroy: %s",
+ __func__, mono_w32handle_ops_typename (type), handle, old, new, new == 0 ? "true" : "false");
+
+ return new == 0;
+}
+
+void mono_w32handle_ref (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to ref handle %p, unknown handle", __func__, handle);
+ return;
+ }
+
+ if (!mono_w32handle_ref_core (handle, handle_data))
+ g_error ("%s: failed to ref handle %p", __func__, handle);
+}
+
+static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer);
+
+/* The handle must not be locked on entry to this function */
+void
+mono_w32handle_unref (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ gboolean destroy;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to unref handle %p, unknown handle",
+ __func__, handle);
+ return;
+ }
+
+ destroy = mono_w32handle_unref_core (handle, handle_data, 1);
+
+ if (destroy) {
+ /* Need to copy the handle info, reset the slot in the
+ * array, and _only then_ call the close function to
+ * avoid race conditions (eg file descriptors being
+ * closed, and another file being opened getting the
+ * same fd racing the memset())
+ */
+ MonoW32HandleType type;
+ gpointer handle_specific;
+ void (*close_func)(gpointer, gpointer);
+
+ type = handle_data->type;
+ handle_specific = handle_data->specific;
+
+ mono_os_mutex_lock (&scan_mutex);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: destroy %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
+
+ mono_os_mutex_destroy (&handle_data->signal_mutex);
+ mono_os_cond_destroy (&handle_data->signal_cond);
+
+ memset (handle_data, 0, sizeof (MonoW32HandleBase));
+
+ mono_os_mutex_unlock (&scan_mutex);
+
+ close_func = _wapi_handle_ops_get_close_func (type);
+ if (close_func != NULL) {
+ close_func (handle, handle_specific);
+ }
+
+ g_free (handle_specific);
+ }
+}
+
+void
+mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops)
+{
+ handle_ops [type] = ops;
+}
+
+void mono_w32handle_register_capabilities (MonoW32HandleType type,
+ MonoW32HandleCapability caps)
+{
+ handle_caps[type] = caps;
+}
+
+gboolean mono_w32handle_test_capabilities (gpointer handle,
+ MonoW32HandleCapability caps)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ type = handle_data->type;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: testing 0x%x against 0x%x (%d)", __func__,
+ handle_caps[type], caps, handle_caps[type] & caps);
+
+ return((handle_caps[type] & caps) != 0);
+}
+
+static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer)
+{
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->close != NULL) {
+ return (handle_ops[type]->close);
+ }
+
+ return (NULL);
+}
+
+void mono_w32handle_ops_close (gpointer handle, gpointer data)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->close != NULL) {
+ handle_ops[type]->close (handle, data);
+ }
+}
+
+void mono_w32handle_ops_details (MonoW32HandleType type, gpointer data)
+{
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->details != NULL) {
+ handle_ops[type]->details (data);
+ }
+}
+
+const gchar* mono_w32handle_ops_typename (MonoW32HandleType type)
+{
+ g_assert (handle_ops [type]);
+ g_assert (handle_ops [type]->typename);
+ return handle_ops [type]->typename ();
+}
+
+gsize mono_w32handle_ops_typesize (MonoW32HandleType type)
+{
+ g_assert (handle_ops [type]);
+ g_assert (handle_ops [type]->typesize);
+ return handle_ops [type]->typesize ();
+}
+
+void mono_w32handle_ops_signal (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
+ handle_ops[type]->signal (handle);
+ }
+}
+
+gboolean mono_w32handle_ops_own (gpointer handle, guint32 *statuscode)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
+ return(handle_ops[type]->own_handle (handle, statuscode));
+ } else {
+ return(FALSE);
+ }
+}
+
+gboolean mono_w32handle_ops_isowned (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) {
+ return(handle_ops[type]->is_owned (handle));
+ } else {
+ return(FALSE);
+ }
+}
+
+guint32 mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean *alerted)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(WAIT_FAILED);
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->special_wait != NULL) {
+ return(handle_ops[type]->special_wait (handle, timeout, alerted));
+ } else {
+ return(WAIT_FAILED);
+ }
+}
+
+void mono_w32handle_ops_prewait (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->prewait != NULL) {
+ handle_ops[type]->prewait (handle);
+ }
+}
+
+static void
+spin (guint32 ms)
+{
+ struct timespec sleepytime;
+
+ g_assert (ms < 1000);
+
+ sleepytime.tv_sec = 0;
+ sleepytime.tv_nsec = ms * 1000000;
+ nanosleep (&sleepytime, NULL);
+}
+
+static void
+mono_w32handle_lock_handles (gpointer *handles, gsize numhandles)
+{
+ guint32 i, iter=0;
+ int thr_ret;
+
+ /* Lock all the handles, with backoff */
+again:
+ for(i=0; i<numhandles; i++) {
+ gpointer handle = handles[i];
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: attempting to lock %p", __func__, handle);
+
+ thr_ret = mono_w32handle_trylock_handle (handle);
+
+ if (thr_ret != 0) {
+ /* Bummer */
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: attempt failed for %p: %s", __func__,
+ handle, strerror (thr_ret));
+
+ while (i--) {
+ handle = handles[i];
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ }
+
+ /* If iter ever reaches 100 the nanosleep will
+ * return EINVAL immediately, but we have a
+ * design flaw if that happens.
+ */
+ iter++;
+ if(iter==100) {
+ g_warning ("%s: iteration overflow!",
+ __func__);
+ iter=1;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Backing off for %d ms", __func__,
+ iter*10);
+ spin (10 * iter);
+
+ goto again;
+ }
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Locked all handles", __func__);
+}
+
+static void
+mono_w32handle_unlock_handles (gpointer *handles, gsize numhandles)
+{
+ guint32 i;
+ int thr_ret;
+
+ for(i=0; i<numhandles; i++) {
+ gpointer handle = handles[i];
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: unlocking handle %p", __func__, handle);
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ }
+}
+
+static int
+mono_w32handle_timedwait_signal_naked (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ int res;
+
+ if (!poll) {
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ /* This is needed when waiting for process handles */
+ if (!alerted) {
+ /*
+ * pthread_cond_(timed)wait() can return 0 even if the condition was not
+ * signalled. This happens at least on Darwin. We surface this, i.e., we
+ * get spurious wake-ups.
+ *
+ * http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html
+ */
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ if (timeout < 100) {
+ /* Real timeout is less than 100ms time */
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ res = mono_os_cond_timedwait (cond, mutex, 100);
+
+ /* Mask the fake timeout, this will cause
+ * another poll if the cond was not really signaled
+ */
+ if (res == -1)
+ res = 0;
+ }
+ }
+ }
+
+ return res;
+}
+
+static void
+signal_global (gpointer unused)
+{
+ /* If we reach here, then interrupt token is set to the flag value, which
+ * means that the target thread is either
+ * - before the first CAS in timedwait, which means it won't enter the wait.
+ * - it is after the first CAS, so it is already waiting, or it will enter
+ * the wait, and it will be interrupted by the broadcast. */
+ mono_os_mutex_lock (&global_signal_mutex);
+ mono_os_cond_broadcast (&global_signal_cond);
+ mono_os_mutex_unlock (&global_signal_mutex);
+}
+
+static int
+mono_w32handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ int res;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: waiting for global", __func__);
+
+ if (alerted)
+ *alerted = FALSE;
+
+ if (alerted) {
+ mono_thread_info_install_interrupt (signal_global, NULL, alerted);
+ if (*alerted)
+ return 0;
+ }
+
+ res = mono_w32handle_timedwait_signal_naked (&global_signal_cond, &global_signal_mutex, timeout, poll, alerted);
+
+ if (alerted)
+ mono_thread_info_uninstall_interrupt (alerted);
+
+ return res;
+}
+
+static void
+signal_handle_and_unref (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ mono_cond_t *cond;
+ mono_mutex_t *mutex;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("cannot signal unknown handle %p", handle);
+
+ /* If we reach here, then interrupt token is set to the flag value, which
+ * means that the target thread is either
+ * - before the first CAS in timedwait, which means it won't enter the wait.
+ * - it is after the first CAS, so it is already waiting, or it will enter
+ * the wait, and it will be interrupted by the broadcast. */
+ cond = &handle_data->signal_cond;
+ mutex = &handle_data->signal_mutex;
+
+ mono_os_mutex_lock (mutex);
+ mono_os_cond_broadcast (cond);
+ mono_os_mutex_unlock (mutex);
+
+ mono_w32handle_unref (handle);
+}
+
+static int
+mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ MonoW32HandleBase *handle_data;
+ int res;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("cannot wait on unknown handle %p", handle);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: waiting for %p (type %s)", __func__, handle,
+ mono_w32handle_ops_typename (mono_w32handle_get_type (handle)));
+
+ if (alerted)
+ *alerted = FALSE;
+
+ if (alerted) {
+ mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
+ if (*alerted)
+ return 0;
+ mono_w32handle_ref (handle);
+ }
+
+ res = mono_w32handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted);
+
+ if (alerted) {
+ mono_thread_info_uninstall_interrupt (alerted);
+ if (!*alerted) {
+ /* if it is alerted, then the handle is unref in the interrupt callback */
+ mono_w32handle_unref (handle);
+ }
+ }
+
+ return res;
+}
+
+static gboolean
+dump_callback (gpointer handle, gpointer handle_specific, gpointer user_data)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("cannot dump unknown handle %p", handle);
+
+ g_print ("%p [%7s] signalled: %5s ref: %3d ",
+ handle, mono_w32handle_ops_typename (handle_data->type), handle_data->signalled ? "true" : "false", handle_data->ref);
+ mono_w32handle_ops_details (handle_data->type, handle_data->specific);
+ g_print ("\n");
+
+ return FALSE;
+}
+
+void mono_w32handle_dump (void)
+{
+ mono_w32handle_foreach (dump_callback, NULL);
+}
+
+static gboolean
+own_if_signalled (gpointer handle, guint32 *statuscode)
+{
+ if (!mono_w32handle_issignalled (handle))
+ return FALSE;
+
+ *statuscode = WAIT_OBJECT_0;
+ mono_w32handle_ops_own (handle, statuscode);
+ return TRUE;
+}
+
+static gboolean
+own_if_owned( gpointer handle, guint32 *statuscode)
+{
+ if (!mono_w32handle_ops_isowned (handle))
+ return FALSE;
+
+ *statuscode = WAIT_OBJECT_0;
+ mono_w32handle_ops_own (handle, statuscode);
+ return TRUE;
+}
+
+MonoW32HandleWaitRet
+mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable)
+{
+ MonoW32HandleWaitRet ret;
+ gboolean alerted;
+ gint64 start;
+ gint thr_ret;
+ guint32 statuscode = 0;
+
+ alerted = FALSE;
+
+ if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p has special wait",
+ __func__, handle);
+
+ switch (mono_w32handle_ops_specialwait (handle, timeout, alertable ? &alerted : NULL)) {
+ case WAIT_OBJECT_0:
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ break;
+ case WAIT_ABANDONED_0:
+ ret = MONO_W32HANDLE_WAIT_RET_ABANDONED_0;
+ break;
+ case WAIT_IO_COMPLETION:
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ break;
+ case WAIT_TIMEOUT:
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ break;
+ case WAIT_FAILED:
+ ret = MONO_W32HANDLE_WAIT_RET_FAILED;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (alerted)
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+
+ return ret;
+ }
+
+ if (!mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_WAIT)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for",
+ __func__, handle);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_OWN)) {
+ if (own_if_owned (handle, &statuscode)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
+ __func__, handle);
+
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+ }
+
+ if (timeout != INFINITE)
+ start = mono_msec_ticks ();
+
+ for (;;) {
+ gint waited;
+
+ if (own_if_signalled (handle, &statuscode)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
+ __func__, handle);
+
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+
+ mono_w32handle_ops_prewait (handle);
+
+ if (timeout == INFINITE) {
+ waited = mono_w32handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &alerted : NULL);
+ } else {
+ gint64 elapsed;
+
+ elapsed = mono_msec_ticks () - start;
+ if (elapsed > timeout) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+
+ waited = mono_w32handle_timedwait_signal_handle (handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL);
+ }
+
+ if (alerted) {
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ goto done;
+ }
+
+ if (waited != 0) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+ }
+
+done:
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ return ret;
+}
+
+MonoW32HandleWaitRet
+mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable)
+{
+ MonoW32HandleWaitRet ret;
+ gboolean alerted, poll;
+ gint i, thr_ret;
+ gint64 start;
+ gpointer handles_sorted [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
+ guint32 statuscodes [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS] = {0};
+
+ if (nhandles == 0)
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+
+ if (nhandles == 1)
+ return mono_w32handle_wait_one (handles [0], timeout, alertable);
+
+ alerted = FALSE;
+
+ if (nhandles > MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: too many handles: %zd",
+ __func__, nhandles);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ for (i = 0; i < nhandles; ++i) {
+ if (!mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_WAIT)
+ && !mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_SPECIAL_WAIT))
+ {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for",
+ __func__, handles [i]);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ handles_sorted [i] = handles [i];
+ }
+
+ qsort (handles_sorted, nhandles, sizeof (gpointer), g_direct_equal);
+ for (i = 1; i < nhandles; ++i) {
+ if (handles_sorted [i - 1] == handles_sorted [i]) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p is duplicated",
+ __func__, handles_sorted [i]);
+
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+ }
+
+ poll = FALSE;
+ for (i = 0; i < nhandles; ++i) {
+ if (mono_w32handle_get_type (handles [i]) == MONO_W32HANDLE_PROCESS) {
+ /* Can't wait for a process handle + another handle without polling */
+ poll = TRUE;
+ }
+ }
+
+ if (timeout != INFINITE)
+ start = mono_msec_ticks ();
+
+ for (i = 0; i < nhandles; ++i) {
+ /* Add a reference, as we need to ensure the handle wont
+ * disappear from under us while we're waiting in the loop
+ * (not lock, as we don't want exclusive access here) */
+ mono_w32handle_ref (handles [i]);
+ }
+
+ for (;;) {
+ gsize count, lowest;
+ gboolean signalled;
+ gint waited;
+
+ count = 0;
+ lowest = nhandles;
+
+ mono_w32handle_lock_handles (handles, nhandles);
+
+ for (i = 0; i < nhandles; i++) {
+ if ((mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_OWN) && mono_w32handle_ops_isowned (handles [i]))
+ || mono_w32handle_issignalled (handles [i]))
+ {
+ count ++;
+
+ if (i < lowest)
+ lowest = i;
+ }
+ }
+
+ signalled = (waitall && count == nhandles) || (!waitall && count > 0);
+
+ if (signalled) {
+ for (i = 0; i < nhandles; i++)
+ own_if_signalled (handles [i], &statuscodes [i]);
+ }
+
+ mono_w32handle_unlock_handles (handles, nhandles);
+
+ if (signalled) {
+ ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + lowest;
+ for (i = lowest; i < nhandles; i++) {
+ if (statuscodes [i] == WAIT_ABANDONED_0) {
+ ret = MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + lowest;
+ break;
+ }
+ }
+ goto done;
+ }
+
+ for (i = 0; i < nhandles; i++) {
+ mono_w32handle_ops_prewait (handles[i]);
+
+ if (mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_SPECIAL_WAIT)
+ && !mono_w32handle_issignalled (handles [i]))
+ {
+ mono_w32handle_ops_specialwait (handles [i], 0, alertable ? &alerted : NULL);
+ }
+ }
+
+ thr_ret = mono_w32handle_lock_signal_mutex ();
+ g_assert (thr_ret == 0);
+
+ if (waitall) {
+ signalled = TRUE;
+ for (i = 0; i < nhandles; ++i) {
+ if (!mono_w32handle_issignalled (handles [i])) {
+ signalled = FALSE;
+ break;
+ }
+ }
+ } else {
+ signalled = FALSE;
+ for (i = 0; i < nhandles; ++i) {
+ if (mono_w32handle_issignalled (handles [i])) {
+ signalled = TRUE;
+ break;
+ }
+ }
+ }
+
+ waited = 0;
+
+ if (!signalled) {
+ if (timeout == INFINITE) {
+ waited = mono_w32handle_timedwait_signal (INFINITE, poll, alertable ? &alerted : NULL);
+ } else {
+ gint64 elapsed;
+
+ elapsed = mono_msec_ticks () - start;
+ if (elapsed > timeout) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+
+ thr_ret = mono_w32handle_unlock_signal_mutex ();
+ g_assert (thr_ret == 0);
+
+ goto done;
+ }
+
+ waited = mono_w32handle_timedwait_signal (timeout - elapsed, poll, alertable ? &alerted : NULL);
+ }
+ }
+
+ thr_ret = mono_w32handle_unlock_signal_mutex ();
+ g_assert (thr_ret == 0);
+
+ if (alerted) {
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ goto done;
+ }
+
+ if (waited != 0) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+ }
+
+done:
+ for (i = 0; i < nhandles; i++) {
+ /* Unref everything we reffed above */
+ mono_w32handle_unref (handles [i]);
+ }
+
+ return ret;
+}
+
+MonoW32HandleWaitRet
+mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable)
+{
+ MonoW32HandleWaitRet ret;
+ gint64 start;
+ gboolean alerted;
+ gint thr_ret;
+ guint32 statuscode = 0;
+
+ alerted = FALSE;
+
+ if (!mono_w32handle_test_capabilities (signal_handle, MONO_W32HANDLE_CAP_SIGNAL))
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ if (!mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_WAIT))
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+
+ if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) {
+ g_warning ("%s: handle %p has special wait, implement me!!", __func__, wait_handle);
+ return MONO_W32HANDLE_WAIT_RET_FAILED;
+ }
+
+ thr_ret = mono_w32handle_lock_handle (wait_handle);
+ g_assert (thr_ret == 0);
+
+ mono_w32handle_ops_signal (signal_handle);
+
+ if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_OWN)) {
+ if (own_if_owned (wait_handle, &statuscode)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
+ __func__, wait_handle);
+
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+ }
+
+ if (timeout != INFINITE)
+ start = mono_msec_ticks ();
+
+ for (;;) {
+ gint waited;
+
+ if (own_if_signalled (wait_handle, &statuscode)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
+ __func__, wait_handle);
+
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ goto done;
+ }
+
+ mono_w32handle_ops_prewait (wait_handle);
+
+ if (timeout == INFINITE) {
+ waited = mono_w32handle_timedwait_signal_handle (wait_handle, INFINITE, FALSE, alertable ? &alerted : NULL);
+ } else {
+ gint64 elapsed;
+
+ elapsed = mono_msec_ticks () - start;
+ if (elapsed > timeout) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+
+ waited = mono_w32handle_timedwait_signal_handle (wait_handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL);
+ }
+
+ if (alerted) {
+ ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
+ goto done;
+ }
+
+ if (waited != 0) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ goto done;
+ }
+ }
+
+done:
+ thr_ret = mono_w32handle_unlock_handle (wait_handle);
+ g_assert (thr_ret == 0);
+
+ return ret;
+}
+
+#endif /* !defined(HOST_WIN32) */
--- /dev/null
+
+#ifndef _MONO_METADATA_W32HANDLE_H_
+#define _MONO_METADATA_W32HANDLE_H_
+
+#include <config.h>
+#include <glib.h>
+
+#ifndef INVALID_HANDLE_VALUE
+#define INVALID_HANDLE_VALUE (gpointer)-1
+#endif
+
+#define MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS 64
+
+typedef enum {
+ MONO_W32HANDLE_UNUSED = 0,
+ MONO_W32HANDLE_FILE,
+ MONO_W32HANDLE_CONSOLE,
+ MONO_W32HANDLE_THREAD,
+ MONO_W32HANDLE_SEM,
+ MONO_W32HANDLE_MUTEX,
+ MONO_W32HANDLE_EVENT,
+ MONO_W32HANDLE_SOCKET,
+ MONO_W32HANDLE_FIND,
+ MONO_W32HANDLE_PROCESS,
+ MONO_W32HANDLE_PIPE,
+ MONO_W32HANDLE_NAMEDMUTEX,
+ MONO_W32HANDLE_NAMEDSEM,
+ MONO_W32HANDLE_NAMEDEVENT,
+ MONO_W32HANDLE_COUNT
+} MonoW32HandleType;
+
+typedef struct
+{
+ void (*close)(gpointer handle, gpointer data);
+
+ /* SignalObjectAndWait */
+ void (*signal)(gpointer signal);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects,
+ * with the handle locked (shared handles aren't locked.)
+ * Returns TRUE if ownership was established, false otherwise.
+ * If TRUE, *statuscode contains a status code such as
+ * WAIT_OBJECT_0 or WAIT_ABANDONED_0.
+ */
+ gboolean (*own_handle)(gpointer handle, guint32 *statuscode);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects, if the
+ * handle in question is "ownable" (ie mutexes), to see if the current
+ * thread already owns this handle
+ */
+ gboolean (*is_owned)(gpointer handle);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects,
+ * if the handle in question needs a special wait function
+ * instead of using the normal handle signal mechanism.
+ * Returns the WaitForSingleObject return code.
+ */
+ guint32 (*special_wait)(gpointer handle, guint32 timeout, gboolean *alerted);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects,
+ * if the handle in question needs some preprocessing before the
+ * signal wait.
+ */
+ void (*prewait)(gpointer handle);
+
+ /* Called when dumping the handles */
+ void (*details)(gpointer data);
+
+ /* Called to get the name of the handle type */
+ const gchar* (*typename) (void);
+
+ /* Called to get the size of the handle type */
+ gsize (*typesize) (void);
+} MonoW32HandleOps;
+
+typedef enum {
+ MONO_W32HANDLE_CAP_WAIT = 0x01,
+ MONO_W32HANDLE_CAP_SIGNAL = 0x02,
+ MONO_W32HANDLE_CAP_OWN = 0x04,
+ MONO_W32HANDLE_CAP_SPECIAL_WAIT = 0x08,
+} MonoW32HandleCapability;
+
+extern guint32 mono_w32handle_fd_reserve;
+
+void
+mono_w32handle_init (void);
+
+void
+mono_w32handle_cleanup (void);
+
+void
+mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops);
+
+gpointer
+mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific);
+
+gpointer
+mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific);
+
+MonoW32HandleType
+mono_w32handle_get_type (gpointer handle);
+
+gboolean
+mono_w32handle_lookup (gpointer handle, MonoW32HandleType type, gpointer *handle_specific);
+
+gpointer
+mono_w32handle_search (MonoW32HandleType type, gboolean (*check)(gpointer, gpointer), gpointer user_data, gpointer *handle_specific, gboolean search_shared);
+
+void
+mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data);
+
+void
+mono_w32handle_dump (void);
+
+void
+mono_w32handle_ref (gpointer handle);
+
+void
+mono_w32handle_unref (gpointer handle);
+
+void
+mono_w32handle_register_capabilities (MonoW32HandleType type, MonoW32HandleCapability caps);
+
+gboolean
+mono_w32handle_test_capabilities (gpointer handle, MonoW32HandleCapability caps);
+
+void
+mono_w32handle_ops_close (gpointer handle, gpointer data);
+
+void
+mono_w32handle_ops_signal (gpointer handle);
+
+gboolean
+mono_w32handle_ops_own (gpointer handle, guint32 *statuscode);
+
+gboolean
+mono_w32handle_ops_isowned (gpointer handle);
+
+guint32
+mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean *alerted);
+
+void
+mono_w32handle_ops_prewait (gpointer handle);
+
+void
+mono_w32handle_ops_details (MonoW32HandleType type, gpointer data);
+
+const gchar*
+mono_w32handle_ops_typename (MonoW32HandleType type);
+
+gsize
+mono_w32handle_ops_typesize (MonoW32HandleType type);
+
+void
+mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast);
+
+gboolean
+mono_w32handle_issignalled (gpointer handle);
+
+int
+mono_w32handle_lock_handle (gpointer handle);
+
+int
+mono_w32handle_trylock_handle (gpointer handle);
+
+int
+mono_w32handle_unlock_handle (gpointer handle);
+
+typedef enum {
+ MONO_W32HANDLE_WAIT_RET_SUCCESS_0 = 0,
+ MONO_W32HANDLE_WAIT_RET_ABANDONED_0 = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS,
+ MONO_W32HANDLE_WAIT_RET_ALERTED = -1,
+ MONO_W32HANDLE_WAIT_RET_TIMEOUT = -2,
+ MONO_W32HANDLE_WAIT_RET_FAILED = -3,
+} MonoW32HandleWaitRet;
+
+MonoW32HandleWaitRet
+mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable);
+
+MonoW32HandleWaitRet
+mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable);
+
+MonoW32HandleWaitRet
+mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable);
+
+#endif /* _MONO_METADATA_W32HANDLE_H_ */
#include "mono/metadata/object-internals.h"
#include "mono/utils/mono-logger-internals.h"
#include "mono/utils/mono-threads.h"
-#include "mono/utils/w32handle.h"
+#include "mono/metadata/w32handle.h"
typedef struct {
MonoNativeThreadId tid;
--- /dev/null
+
+#ifndef _MONO_METADATA_W32PROCESS_INTERNALS_H_
+#define _MONO_METADATA_W32PROCESS_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "io-layer/io-layer.h"
+
+#if !defined(HOST_WIN32)
+
+guint32
+mono_w32process_get_pid (gpointer handle);
+
+gboolean
+mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed);
+
+guint32
+mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 *basename, guint32 size);
+
+guint32
+mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 *basename, guint32 size);
+
+gboolean
+mono_w32process_module_get_information (gpointer process, gpointer module, MODULEINFO *modinfo, guint32 size);
+
+#endif /* !defined(HOST_WIN32) */
+
+#endif /* _MONO_METADATA_W32PROCESS_INTERNALS_H_ */
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_BSD_BACKEND
+
+#include <errno.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#if !defined(__OpenBSD__)
+#include <sys/utsname.h>
+#endif
+#if defined(__FreeBSD__)
+#include <sys/user.h> /* struct kinfo_proc */
+#endif
+
+#include <link.h>
+
+#include "utils/mono-logger-internals.h"
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ gint mib [6];
+ gsize size;
+ struct kinfo_proc *pi;
+ gchar *ret;
+
+#if defined(__FreeBSD__)
+ mib [0] = CTL_KERN;
+ mib [1] = KERN_PROC;
+ mib [2] = KERN_PROC_PID;
+ mib [3] = pid;
+ if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
+ return NULL;
+ }
+
+ if ((pi = g_malloc (size)) == NULL)
+ return NULL;
+
+ if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
+ if (errno == ENOMEM) {
+ g_free (pi);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
+ }
+ return NULL;
+ }
+
+ ret = strlen (pi->ki_comm) > 0 ? g_strdup (pi->ki_comm) : NULL;
+
+ g_free (pi);
+#elif defined(__OpenBSD__)
+ mib [0] = CTL_KERN;
+ mib [1] = KERN_PROC;
+ mib [2] = KERN_PROC_PID;
+ mib [3] = pid;
+ mib [4] = sizeof(struct kinfo_proc);
+ mib [5] = 0;
+
+retry:
+ if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
+ return NULL;
+ }
+
+ if ((pi = g_malloc (size)) == NULL)
+ return NULL;
+
+ mib[5] = (int)(size / sizeof(struct kinfo_proc));
+
+ if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
+ (size != sizeof (struct kinfo_proc))) {
+ if (errno == ENOMEM) {
+ g_free (pi);
+ goto retry;
+ }
+ return NULL;
+ }
+
+ ret = strlen (pi->p_comm) > 0 ? g_strdup (pi->p_comm) : NULL;
+
+ g_free (pi);
+#endif
+
+ return ret;
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+ return mono_w32process_get_name (pid);
+}
+
+static gint
+mono_w32process_get_modules_callback (struct dl_phdr_info *info, gsize size, gpointer ptr)
+{
+ if (size < offsetof (struct dl_phdr_info, dlpi_phnum) + sizeof (info->dlpi_phnum))
+ return (-1);
+
+ struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info));
+ if (!cpy)
+ return (-1);
+
+ memcpy(cpy, info, sizeof(*info));
+
+ g_ptr_array_add ((GPtrArray *)ptr, cpy);
+
+ return (0);
+}
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ MonoW32ProcessModule *mod;
+ GPtrArray *dlarray = g_ptr_array_new();
+ gint i;
+
+ if (dl_iterate_phdr (mono_w32process_get_modules_callback, dlarray) < 0)
+ return NULL;
+
+ for (i = 0; i < dlarray->len; i++) {
+ struct dl_phdr_info *info = g_ptr_array_index (dlarray, i);
+
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = (gpointer)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
+ mod->address_end = (gpointer)(info->dlpi_addr + info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr);
+ mod->perms = g_strdup ("r--p");
+ mod->address_offset = 0;
+ mod->inode = i;
+ mod->filename = g_strdup (info->dlpi_name);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p",
+ __func__, mod->inode, mod->filename, mod->address_start, mod->address_end);
+
+ g_free (info);
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ g_ptr_array_free (dlarray, TRUE);
+
+ return g_slist_reverse (ret);
+}
+
+#endif
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_DEFAULT_BACKEND
+
+#include <unistd.h>
+
+#ifdef PLATFORM_SOLARIS
+/* procfs.h cannot be included if this define is set, but it seems to work fine if it is undefined */
+#if _FILE_OFFSET_BITS == 64
+#undef _FILE_OFFSET_BITS
+#include <procfs.h>
+#define _FILE_OFFSET_BITS 64
+#else
+#include <procfs.h>
+#endif
+#endif
+
+#include "utils/mono-logger-internals.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 242
+#endif
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ FILE *fp;
+ gchar *filename;
+ gchar buf[256];
+ gchar *ret = NULL;
+
+#if defined(PLATFORM_SOLARIS)
+ filename = g_strdup_printf ("/proc/%d/psinfo", pid);
+ if ((fp = fopen (filename, "r")) != NULL) {
+ struct psinfo info;
+ int nread;
+
+ nread = fread (&info, sizeof (info), 1, fp);
+ if (nread == 1) {
+ ret = g_strdup (info.pr_fname);
+ }
+
+ fclose (fp);
+ }
+ g_free (filename);
+#else
+ memset (buf, '\0', sizeof(buf));
+ filename = g_strdup_printf ("/proc/%d/exe", pid);
+ if (readlink (filename, buf, 255) > 0) {
+ ret = g_strdup (buf);
+ }
+ g_free (filename);
+
+ if (ret != NULL) {
+ return(ret);
+ }
+
+ filename = g_strdup_printf ("/proc/%d/cmdline", pid);
+ if ((fp = fopen (filename, "r")) != NULL) {
+ if (fgets (buf, 256, fp) != NULL) {
+ ret = g_strdup (buf);
+ }
+
+ fclose (fp);
+ }
+ g_free (filename);
+
+ if (ret != NULL) {
+ return(ret);
+ }
+
+ filename = g_strdup_printf ("/proc/%d/stat", pid);
+ if ((fp = fopen (filename, "r")) != NULL) {
+ if (fgets (buf, 256, fp) != NULL) {
+ char *start, *end;
+
+ start = strchr (buf, '(');
+ if (start != NULL) {
+ end = strchr (start + 1, ')');
+
+ if (end != NULL) {
+ ret = g_strndup (start + 1,
+ end - start - 1);
+ }
+ }
+ }
+
+ fclose (fp);
+ }
+ g_free (filename);
+#endif
+
+ return ret;
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+ return mono_w32process_get_name (pid);
+}
+
+static FILE *
+open_process_map (int pid, const char *mode)
+{
+ gint i;
+ const gchar *proc_path[] = {
+ "/proc/%d/maps", /* GNU/Linux */
+ "/proc/%d/map", /* FreeBSD */
+ NULL
+ };
+
+ for (i = 0; proc_path [i]; i++) {
+ gchar *filename;
+ FILE *fp;
+
+ filename = g_strdup_printf (proc_path[i], pid);
+ fp = fopen (filename, mode);
+ g_free (filename);
+
+ if (fp)
+ return fp;
+ }
+
+ return NULL;
+}
+
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ FILE *fp;
+ MonoW32ProcessModule *mod;
+ gchar buf[MAXPATHLEN + 1], *p, *endp;
+ gchar *start_start, *end_start, *prot_start, *offset_start;
+ gchar *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
+ gpointer address_start, address_end, address_offset;
+ guint32 maj_dev, min_dev;
+ guint64 inode;
+ guint64 device;
+
+ fp = open_process_map (pid, "r");
+ if (!fp)
+ return NULL;
+
+ while (fgets (buf, sizeof(buf), fp)) {
+ p = buf;
+ while (g_ascii_isspace (*p)) ++p;
+ start_start = p;
+ if (!g_ascii_isxdigit (*start_start)) {
+ continue;
+ }
+ address_start = (gpointer)strtoul (start_start, &endp, 16);
+ p = endp;
+ if (*p != '-') {
+ continue;
+ }
+
+ ++p;
+ end_start = p;
+ if (!g_ascii_isxdigit (*end_start)) {
+ continue;
+ }
+ address_end = (gpointer)strtoul (end_start, &endp, 16);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ while (g_ascii_isspace (*p)) ++p;
+ prot_start = p;
+ if (*prot_start != 'r' && *prot_start != '-') {
+ continue;
+ }
+ memcpy (prot_buf, prot_start, 4);
+ prot_buf[4] = '\0';
+ while (!g_ascii_isspace (*p)) ++p;
+
+ while (g_ascii_isspace (*p)) ++p;
+ offset_start = p;
+ if (!g_ascii_isxdigit (*offset_start)) {
+ continue;
+ }
+ address_offset = (gpointer)strtoul (offset_start, &endp, 16);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ while(g_ascii_isspace (*p)) ++p;
+ maj_dev_start = p;
+ if (!g_ascii_isxdigit (*maj_dev_start)) {
+ continue;
+ }
+ maj_dev = strtoul (maj_dev_start, &endp, 16);
+ p = endp;
+ if (*p != ':') {
+ continue;
+ }
+
+ ++p;
+ min_dev_start = p;
+ if (!g_ascii_isxdigit (*min_dev_start)) {
+ continue;
+ }
+ min_dev = strtoul (min_dev_start, &endp, 16);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ while (g_ascii_isspace (*p)) ++p;
+ inode_start = p;
+ if (!g_ascii_isxdigit (*inode_start)) {
+ continue;
+ }
+ inode = (guint64)strtol (inode_start, &endp, 10);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ device = makedev ((int)maj_dev, (int)min_dev);
+ if ((device == 0) && (inode == 0)) {
+ continue;
+ }
+
+ while(g_ascii_isspace (*p)) ++p;
+ /* p now points to the filename */
+
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = address_start;
+ mod->address_end = address_end;
+ mod->perms = g_strdup (prot_buf);
+ mod->address_offset = address_offset;
+ mod->device = device;
+ mod->inode = inode;
+ mod->filename = g_strdup (g_strstrip (p));
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ ret = g_slist_reverse (ret);
+
+ fclose (fp);
+
+ return(ret);
+}
+
+#endif
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_HAIKU_BACKEND
+
+#include <KernelKit.h>
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ image_info imageInfo;
+ int32 cookie = 0;
+
+ if (get_next_image_info ((team_id) pid, &cookie, &imageInfo) != B_OK)
+ return NULL;
+
+ return g_strdup (imageInfo.name);
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+ return mono_w32process_get_name (pid);
+}
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ MonoW32ProcessModule *mod;
+ gint32 cookie = 0;
+ image_info imageInfo;
+
+ while (get_next_image_info (B_CURRENT_TEAM, &cookie, &imageInfo) == B_OK) {
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->device = imageInfo.device;
+ mod->inode = imageInfo.node;
+ mod->filename = g_strdup (imageInfo.name);
+ mod->address_start = MIN (imageInfo.text, imageInfo.data);
+ mod->address_end = MAX ((uint8_t*)imageInfo.text + imageInfo.text_size,
+ (uint8_t*)imageInfo.data + imageInfo.data_size);
+ mod->perms = g_strdup ("r--p");
+ mod->address_offset = 0;
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ return g_slist_reverse (ret);
+}
+
+#endif
--- /dev/null
+
+#ifndef _MONO_METADATA_W32PROCESS_UNIX_INTERNALS_H_
+#define _MONO_METADATA_W32PROCESS_UNIX_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+/*
+ * FOR EXCLUSIVE USE BY w32process-unix.c
+ */
+
+#if defined(PLATFORM_MACOSX)
+#define USE_OSX_BACKEND
+#elif (defined(__OpenBSD__) || defined(__FreeBSD__)) && defined(HAVE_LINK_H)
+#define USE_BSD_BACKEND
+#elif defined(__HAIKU__)
+#define USE_HAIKU_BACKEND
+#else
+#define USE_DEFAULT_BACKEND
+#endif
+
+typedef struct {
+ gpointer address_start;
+ gpointer address_end;
+ gchar *perms;
+ gpointer address_offset;
+ guint64 device;
+ guint64 inode;
+ gchar *filename;
+} MonoW32ProcessModule;
+
+gchar*
+mono_w32process_get_name (pid_t pid);
+
+GSList*
+mono_w32process_get_modules (pid_t pid);
+
+static void
+mono_w32process_module_free (MonoW32ProcessModule *module)
+{
+ g_free (module->perms);
+ g_free (module->filename);
+ g_free (module);
+}
+
+/*
+ * Used to look through the GSList* returned by mono_w32process_get_modules
+ */
+static gint
+mono_w32process_module_equals (gconstpointer a, gconstpointer b)
+{
+ MonoW32ProcessModule *want = (MonoW32ProcessModule *)a;
+ MonoW32ProcessModule *compare = (MonoW32ProcessModule *)b;
+ return (want->device == compare->device && want->inode == compare->inode) ? 0 : 1;
+}
+
+#endif /* _MONO_METADATA_W32PROCESS_UNIX_INTERNALS_H_ */
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_OSX_BACKEND
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <mach-o/dyld.h>
+#include <mach-o/getsect.h>
+
+/* sys/resource.h (for rusage) is required when using osx 10.3 (but not 10.4) */
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#include <sys/resource.h>
+#ifdef HAVE_LIBPROC_H
+/* proc_name */
+#include <libproc.h>
+#endif
+#endif
+
+#include "utils/mono-logger-internals.h"
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ gchar *ret = NULL;
+
+#if defined (__mono_ppc__) || !defined (TARGET_OSX)
+ size_t size;
+ struct kinfo_proc *pi;
+ gint mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
+
+ if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
+ return(ret);
+
+ if ((pi = g_malloc (size)) == NULL)
+ return(ret);
+
+ if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
+ if (errno == ENOMEM) {
+ g_free (pi);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
+ }
+ return(ret);
+ }
+
+ if (strlen (pi->kp_proc.p_comm) > 0)
+ ret = g_strdup (pi->kp_proc.p_comm);
+
+ g_free (pi);
+#else
+ gchar buf[256];
+
+ /* No proc name on OSX < 10.5 nor ppc nor iOS */
+ memset (buf, '\0', sizeof(buf));
+ proc_name (pid, buf, sizeof(buf));
+
+ // Fixes proc_name triming values to 15 characters #32539
+ if (strlen (buf) >= MAXCOMLEN - 1) {
+ gchar path_buf [PROC_PIDPATHINFO_MAXSIZE];
+ gchar *name_buf;
+ gint path_len;
+
+ memset (path_buf, '\0', sizeof(path_buf));
+ path_len = proc_pidpath (pid, path_buf, sizeof(path_buf));
+
+ if (path_len > 0 && path_len < sizeof(path_buf)) {
+ name_buf = path_buf + path_len;
+ for(;name_buf > path_buf; name_buf--) {
+ if (name_buf [0] == '/') {
+ name_buf++;
+ break;
+ }
+ }
+
+ if (memcmp (buf, name_buf, MAXCOMLEN - 1) == 0)
+ ret = g_strdup (name_buf);
+ }
+ }
+
+ if (ret == NULL && strlen (buf) > 0)
+ ret = g_strdup (buf);
+#endif
+
+ return ret;
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+#if defined(__mono_ppc__) || !defined(TARGET_OSX)
+ return mono_w32process_get_name (pid);
+#else
+ gchar buf [PROC_PIDPATHINFO_MAXSIZE];
+ gint res;
+
+ res = proc_pidpath (pid, buf, sizeof (buf));
+ if (res <= 0)
+ return NULL;
+ if (buf [0] == '\0')
+ return NULL;
+ return g_strdup (buf);
+#endif
+}
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ MonoW32ProcessModule *mod;
+ guint32 count = _dyld_image_count ();
+ int i = 0;
+
+ for (i = 0; i < count; i++) {
+#if SIZEOF_VOID_P == 8
+ const struct mach_header_64 *hdr;
+ const struct section_64 *sec;
+#else
+ const struct mach_header *hdr;
+ const struct section *sec;
+#endif
+ const char *name;
+
+ name = _dyld_get_image_name (i);
+#if SIZEOF_VOID_P == 8
+ hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
+ sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
+#else
+ hdr = _dyld_get_image_header (i);
+ sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
+#endif
+
+ /* Some dynlibs do not have data sections on osx (#533893) */
+ if (sec == 0)
+ continue;
+
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = GINT_TO_POINTER (sec->addr);
+ mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
+ mod->perms = g_strdup ("r--p");
+ mod->address_offset = 0;
+ mod->device = makedev (0, 0);
+ mod->inode = i;
+ mod->filename = g_strdup (name);
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ return g_slist_reverse (ret);
+}
+
+#endif
--- /dev/null
+/*
+ * process.c: System.Diagnostics.Process support
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * Copyright 2002-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <sched.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <sys/time.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <ctype.h>
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#include <mono/metadata/w32process.h>
+#include <mono/metadata/w32process-internals.h>
+#include <mono/metadata/w32process-unix-internals.h>
+#include <mono/metadata/class.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/exception.h>
+#include <mono/io-layer/io-layer.h>
+#include <mono/metadata/w32handle.h>
+#include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/strenc.h>
+#include <mono/utils/mono-proclib.h>
+#include <mono/utils/mono-path.h>
+#include <mono/utils/mono-lazy-init.h>
+#include <mono/utils/mono-signal-handler.h>
+#include <mono/utils/mono-time.h>
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 242
+#endif
+
+#define STILL_ACTIVE ((int) 0x00000103)
+
+#define LOGDEBUG(...)
+/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
+
+/* The process' environment strings */
+#if defined(__APPLE__)
+#if defined (TARGET_OSX)
+/* Apple defines this in crt_externs.h but doesn't provide that header for
+ * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
+ * in fact exist on all implementations (so far)
+ */
+gchar ***_NSGetEnviron(void);
+#define environ (*_NSGetEnviron())
+#else
+static char *mono_environ[1] = { NULL };
+#define environ mono_environ
+#endif /* defined (TARGET_OSX) */
+#else
+extern char **environ;
+#endif
+
+/*
+ * Handles > _WAPI_PROCESS_UNHANDLED are pseudo handles which represent processes
+ * not started by the runtime.
+ */
+/* This marks a system process that we don't have a handle on */
+/* FIXME: Cope with PIDs > sizeof guint */
+#define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1))
+
+#define WAPI_IS_PSEUDO_PROCESS_HANDLE(handle) ((GPOINTER_TO_UINT(handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED)
+#define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid))
+#define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED)
+
+typedef enum {
+ STARTF_USESHOWWINDOW=0x001,
+ STARTF_USESIZE=0x002,
+ STARTF_USEPOSITION=0x004,
+ STARTF_USECOUNTCHARS=0x008,
+ STARTF_USEFILLATTRIBUTE=0x010,
+ STARTF_RUNFULLSCREEN=0x020,
+ STARTF_FORCEONFEEDBACK=0x040,
+ STARTF_FORCEOFFFEEDBACK=0x080,
+ STARTF_USESTDHANDLES=0x100
+} StartupFlags;
+
+typedef struct {
+ gpointer input;
+ gpointer output;
+ gpointer error;
+} StartupHandles;
+
+typedef struct {
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ guint32 highDateTime;
+ guint32 lowDateTime;
+#else
+ guint32 lowDateTime;
+ guint32 highDateTime;
+#endif
+} ProcessTime;
+
+/*
+ * MonoProcess describes processes we create.
+ * It contains a semaphore that can be waited on in order to wait
+ * for process termination. It's accessed in our SIGCHLD handler,
+ * when status is updated (and pid cleared, to not clash with
+ * subsequent processes that may get executed).
+ */
+typedef struct _MonoProcess MonoProcess;
+struct _MonoProcess {
+ pid_t pid; /* the pid of the process. This value is only valid until the process has exited. */
+ MonoSemType exit_sem; /* this semaphore will be released when the process exits */
+ int status; /* the exit status */
+ gint32 handle_count; /* the number of handles to this mono_process instance */
+ /* we keep a ref to the creating _WapiHandle_process handle until
+ * the process has exited, so that the information there isn't lost.
+ */
+ gpointer handle;
+ gboolean freeable;
+ MonoProcess *next;
+};
+
+/* MonoW32HandleProcess is a structure containing all the required information for process handling. */
+typedef struct {
+ pid_t id;
+ guint32 exitstatus;
+ gpointer main_thread;
+ WapiFileTime create_time;
+ WapiFileTime exit_time;
+ char *proc_name;
+ size_t min_working_set;
+ size_t max_working_set;
+ gboolean exited;
+ MonoProcess *mono_process;
+} MonoW32HandleProcess;
+
+#if HAVE_SIGACTION
+static mono_lazy_init_t process_sig_chld_once = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+#endif
+
+static gchar *cli_launcher;
+
+/* The signal-safe logic to use mono_processes goes like this:
+ * - The list must be safe to traverse for the signal handler at all times.
+ * It's safe to: prepend an entry (which is a single store to 'mono_processes'),
+ * unlink an entry (assuming the unlinked entry isn't freed and doesn't
+ * change its 'next' pointer so that it can still be traversed).
+ * When cleaning up we first unlink an entry, then we verify that
+ * the read lock isn't locked. Then we can free the entry, since
+ * we know that nobody is using the old version of the list (including
+ * the unlinked entry).
+ * We also need to lock when adding and cleaning up so that those two
+ * operations don't mess with eachother. (This lock is not used in the
+ * signal handler) */
+static MonoProcess *mono_processes;
+static mono_mutex_t mono_processes_mutex;
+static volatile gint32 mono_processes_cleaning_up;
+
+static gpointer current_process;
+
+static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 };
+static const gunichar2 *utf16_space = utf16_space_bytes;
+static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 };
+static const gunichar2 *utf16_quote = utf16_quote_bytes;
+
+static void
+process_details (gpointer data)
+{
+ MonoW32HandleProcess *process_handle = (MonoW32HandleProcess *) data;
+ g_print ("id: %d, exited: %s, exitstatus: %d",
+ process_handle->id, process_handle->exited ? "true" : "false", process_handle->exitstatus);
+}
+
+static const gchar*
+process_typename (void)
+{
+ return "Process";
+}
+
+static gsize
+process_typesize (void)
+{
+ return sizeof (MonoW32HandleProcess);
+}
+
+static guint32
+process_wait (gpointer handle, guint32 timeout, gboolean *alerted)
+{
+ MonoW32HandleProcess *process_handle;
+ pid_t pid G_GNUC_UNUSED, ret;
+ int status;
+ gint64 start, now;
+ MonoProcess *mp;
+ gboolean res;
+
+ /* FIXME: We can now easily wait on processes that aren't our own children,
+ * but WaitFor*Object won't call us for pseudo handles. */
+ g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u)", __func__, handle, timeout);
+
+ if (alerted)
+ *alerted = FALSE;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ g_warning ("%s: error looking up process handle %p", __func__, handle);
+ return WAIT_FAILED;
+ }
+
+ if (process_handle->exited) {
+ /* We've already done this one */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Process already exited", __func__, handle, timeout);
+ return WAIT_OBJECT_0;
+ }
+
+ pid = process_handle->id;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): PID: %d", __func__, handle, timeout, pid);
+
+ /* We don't need to lock mono_processes here, the entry
+ * has a handle_count > 0 which means it will not be freed. */
+ mp = process_handle->mono_process;
+ if (!mp) {
+ pid_t res;
+
+ if (pid == mono_process_current_pid ()) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on current process", __func__, handle, timeout);
+ return WAIT_TIMEOUT;
+ }
+
+ /* This path is used when calling Process.HasExited, so
+ * it is only used to poll the state of the process, not
+ * to actually wait on it to exit */
+ g_assert (timeout == 0);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on non-child process", __func__, handle, timeout);
+
+ res = waitpid (pid, &status, WNOHANG);
+ if (res == 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_TIMEOUT", __func__, handle, timeout);
+ return WAIT_TIMEOUT;
+ }
+ if (res > 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process waited successfully", __func__, handle, timeout);
+ return WAIT_OBJECT_0;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_FAILED, error : %s (%d))", __func__, handle, timeout, g_strerror (errno), errno);
+ return WAIT_FAILED;
+ }
+
+ start = mono_msec_ticks ();
+ now = start;
+
+ while (1) {
+ if (timeout != INFINITE) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore for %li ms...",
+ __func__, handle, timeout, (long)(timeout - (now - start)));
+ ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore forever...",
+ __func__, handle, timeout);
+ ret = mono_os_sem_wait (&mp->exit_sem, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
+ }
+
+ if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
+ /* Success, process has exited */
+ mono_os_sem_post (&mp->exit_sem);
+ break;
+ }
+
+ 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;
+ }
+
+ now = mono_msec_ticks ();
+ if (now - start >= timeout) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
+ return WAIT_TIMEOUT;
+ }
+
+ if (alerted && 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);
+ *alerted = TRUE;
+ return WAIT_IO_COMPLETION;
+ }
+ }
+
+ /* Process must have exited */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Waited successfully", __func__, handle, timeout);
+
+ status = mp ? mp->status : 0;
+ if (WIFSIGNALED (status))
+ process_handle->exitstatus = 128 + WTERMSIG (status);
+ else
+ process_handle->exitstatus = WEXITSTATUS (status);
+ _wapi_time_t_to_filetime (time (NULL), &process_handle->exit_time);
+
+ process_handle->exited = TRUE;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Setting pid %d signalled, exit status %d",
+ __func__, handle, timeout, process_handle->id, process_handle->exitstatus);
+
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+
+ return WAIT_OBJECT_0;
+}
+
+static void
+processes_cleanup (void)
+{
+ MonoProcess *mp;
+ MonoProcess *prev = NULL;
+ GSList *finished = NULL;
+ GSList *l;
+ gpointer unref_handle;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
+
+ /* Ensure we're not in here in multiple threads at once, nor recursive. */
+ if (InterlockedCompareExchange (&mono_processes_cleaning_up, 1, 0) != 0)
+ return;
+
+ for (mp = mono_processes; mp; mp = mp->next) {
+ if (mp->pid == 0 && mp->handle) {
+ /* This process has exited and we need to remove the artifical ref
+ * on the handle */
+ mono_os_mutex_lock (&mono_processes_mutex);
+ unref_handle = mp->handle;
+ mp->handle = NULL;
+ mono_os_mutex_unlock (&mono_processes_mutex);
+ if (unref_handle)
+ mono_w32handle_unref (unref_handle);
+ }
+ }
+
+ /*
+ * Remove processes which exited from the mono_processes list.
+ * We need to synchronize with the sigchld handler here, which runs
+ * asynchronously. The handler requires that the mono_processes list
+ * remain valid.
+ */
+ mono_os_mutex_lock (&mono_processes_mutex);
+
+ mp = mono_processes;
+ while (mp) {
+ if (mp->handle_count == 0 && mp->freeable) {
+ /*
+ * Unlink the entry.
+ * This code can run parallel with the sigchld handler, but the
+ * modifications it makes are safe.
+ */
+ if (mp == mono_processes)
+ mono_processes = mp->next;
+ else
+ prev->next = mp->next;
+ finished = g_slist_prepend (finished, mp);
+
+ mp = mp->next;
+ } else {
+ prev = mp;
+ mp = mp->next;
+ }
+ }
+
+ mono_memory_barrier ();
+
+ for (l = finished; l; l = l->next) {
+ /*
+ * All the entries in the finished list are unlinked from mono_processes, and
+ * they have the 'finished' flag set, which means the sigchld handler is done
+ * accessing them.
+ */
+ mp = (MonoProcess *)l->data;
+ mono_os_sem_destroy (&mp->exit_sem);
+ g_free (mp);
+ }
+ g_slist_free (finished);
+
+ mono_os_mutex_unlock (&mono_processes_mutex);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s done", __func__);
+
+ InterlockedDecrement (&mono_processes_cleaning_up);
+}
+
+static void
+process_close (gpointer handle, gpointer data)
+{
+ MonoW32HandleProcess *process_handle;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
+
+ process_handle = (MonoW32HandleProcess *) data;
+ g_free (process_handle->proc_name);
+ process_handle->proc_name = NULL;
+ if (process_handle->mono_process)
+ InterlockedDecrement (&process_handle->mono_process->handle_count);
+ processes_cleanup ();
+}
+
+static MonoW32HandleOps process_ops = {
+ process_close, /* close_shared */
+ NULL, /* signal */
+ NULL, /* own */
+ NULL, /* is_owned */
+ process_wait, /* special_wait */
+ NULL, /* prewait */
+ process_details, /* details */
+ process_typename, /* typename */
+ process_typesize, /* typesize */
+};
+
+static void
+process_set_defaults (MonoW32HandleProcess *process_handle)
+{
+ /* These seem to be the defaults on w2k */
+ process_handle->min_working_set = 204800;
+ process_handle->max_working_set = 1413120;
+
+ _wapi_time_t_to_filetime (time (NULL), &process_handle->create_time);
+}
+
+static void
+process_set_name (MonoW32HandleProcess *process_handle)
+{
+ char *progname, *utf8_progname, *slash;
+
+ progname = g_get_prgname ();
+ utf8_progname = mono_utf8_from_external (progname);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: using [%s] as prog name", __func__, progname);
+
+ if (utf8_progname) {
+ slash = strrchr (utf8_progname, '/');
+ if (slash)
+ process_handle->proc_name = g_strdup (slash+1);
+ else
+ process_handle->proc_name = g_strdup (utf8_progname);
+ g_free (utf8_progname);
+ }
+}
+
+void
+mono_w32process_init (void)
+{
+ MonoW32HandleProcess process_handle;
+
+ mono_w32handle_register_ops (MONO_W32HANDLE_PROCESS, &process_ops);
+
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_PROCESS,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT));
+
+ memset (&process_handle, 0, sizeof (process_handle));
+ process_handle.id = wapi_getpid ();
+ process_set_defaults (&process_handle);
+ process_set_name (&process_handle);
+
+ current_process = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
+ g_assert (current_process);
+
+ mono_os_mutex_init (&mono_processes_mutex);
+}
+
+void
+mono_w32process_cleanup (void)
+{
+ g_free (cli_launcher);
+}
+
+/* Check if a pid is valid - i.e. if a process exists with this pid. */
+static gboolean
+is_pid_valid (pid_t pid)
+{
+ gboolean result = FALSE;
+
+#if defined(HOST_WATCHOS)
+ result = TRUE; // TODO: Rewrite using sysctl
+#elif defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__FreeBSD__)
+ if (((kill(pid, 0) == 0) || (errno == EPERM)) && pid != 0)
+ result = TRUE;
+#elif defined(__HAIKU__)
+ team_info teamInfo;
+ if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
+ result = TRUE;
+#else
+ char *dir = g_strdup_printf ("/proc/%d", pid);
+ if (!access (dir, F_OK))
+ result = TRUE;
+ g_free (dir);
+#endif
+
+ return result;
+}
+
+static int
+len16 (const gunichar2 *str)
+{
+ int len = 0;
+
+ while (*str++ != 0)
+ len++;
+
+ return len;
+}
+
+static gunichar2 *
+utf16_concat (const gunichar2 *first, ...)
+{
+ va_list args;
+ int total = 0, i;
+ const gunichar2 *s;
+ const gunichar2 *p;
+ gunichar2 *ret;
+
+ va_start (args, first);
+ total += len16 (first);
+ for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg(args, gunichar2 *))
+ total += len16 (s);
+ va_end (args);
+
+ ret = g_new (gunichar2, total + 1);
+ if (ret == NULL)
+ return NULL;
+
+ ret [total] = 0;
+ i = 0;
+ for (s = first; *s != 0; s++)
+ ret [i++] = *s;
+ va_start (args, first);
+ for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg (args, gunichar2 *)){
+ for (p = s; *p != 0; p++)
+ ret [i++] = *p;
+ }
+ va_end (args);
+
+ return ret;
+}
+
+guint32
+mono_w32process_get_pid (gpointer handle)
+{
+ MonoW32HandleProcess *process_handle;
+ gboolean res;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ return WAPI_HANDLE_TO_PID (handle);
+ }
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
+ return process_handle->id;
+}
+
+static gboolean
+process_open_compare (gpointer handle, gpointer user_data)
+{
+ gboolean res;
+ MonoW32HandleProcess *process_handle;
+ pid_t wanted_pid, checking_pid;
+
+ g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res)
+ g_error ("%s: unknown process handle %p", __func__, handle);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking at process %d", __func__, process_handle->id);
+
+ checking_pid = process_handle->id;
+ if (checking_pid == 0)
+ return FALSE;
+
+ wanted_pid = GPOINTER_TO_UINT (user_data);
+
+ /* It's possible to have more than one process handle with the
+ * same pid, but only the one running process can be
+ * unsignalled.
+ * If the handle is blown away in the window between
+ * returning TRUE here and mono_w32handle_search pinging
+ * the timestamp, the search will continue. */
+ return checking_pid == wanted_pid && !mono_w32handle_issignalled (handle);
+}
+
+HANDLE
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
+{
+ gpointer handle;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for process %d", __func__, pid);
+
+ handle = mono_w32handle_search (MONO_W32HANDLE_PROCESS, process_open_compare, GUINT_TO_POINTER (pid), NULL, TRUE);
+ if (handle) {
+ /* mono_w32handle_search () already added a ref */
+ return handle;
+ }
+
+ if (is_pid_valid (pid)) {
+ /* Return a pseudo handle for processes we don't have handles for */
+ return WAPI_PID_TO_HANDLE (pid);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find pid %d", __func__, pid);
+
+ SetLastError (ERROR_PROC_NOT_FOUND);
+ return NULL;
+ }
+}
+
+static gboolean
+match_procname_to_modulename (char *procname, char *modulename)
+{
+ char* lastsep = NULL;
+ char* lastsep2 = NULL;
+ char* pname = NULL;
+ char* mname = NULL;
+ gboolean result = FALSE;
+
+ if (procname == NULL || modulename == NULL)
+ return (FALSE);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: procname=\"%s\", modulename=\"%s\"", __func__, procname, modulename);
+ pname = mono_path_resolve_symlinks (procname);
+ mname = mono_path_resolve_symlinks (modulename);
+
+ if (!strcmp (pname, mname))
+ result = TRUE;
+
+ if (!result) {
+ lastsep = strrchr (mname, '/');
+ if (lastsep)
+ if (!strcmp (lastsep+1, pname))
+ result = TRUE;
+ if (!result) {
+ lastsep2 = strrchr (pname, '/');
+ if (lastsep2){
+ if (lastsep) {
+ if (!strcmp (lastsep+1, lastsep2+1))
+ result = TRUE;
+ } else {
+ if (!strcmp (mname, lastsep2+1))
+ result = TRUE;
+ }
+ }
+ }
+ }
+
+ g_free (pname);
+ g_free (mname);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: result is %d", __func__, result);
+ return result;
+}
+
+gboolean
+mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed)
+{
+ MonoW32HandleProcess *process_handle;
+ GSList *mods = NULL;
+ MonoW32ProcessModule *module;
+ guint32 count, avail = size / sizeof(gpointer);
+ int i;
+ pid_t pid;
+ char *proc_name = NULL;
+ gboolean res;
+
+ /* Store modules in an array of pointers (main module as
+ * modules[0]), using the load address for each module as a
+ * token. (Use 'NULL' as an alternative for the main module
+ * so that the simple implementation can just return one item
+ * for now.) Get the info from /proc/<pid>/maps on linux,
+ * /proc/<pid>/map on FreeBSD, other systems will have to
+ * implement /dev/kmem reading or whatever other horrid
+ * technique is needed.
+ */
+ if (size < sizeof(gpointer))
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+ pid = WAPI_HANDLE_TO_PID (process);
+ proc_name = mono_w32process_get_name (pid);
+ } else {
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ proc_name = g_strdup (process_handle->proc_name);
+ }
+
+ if (!proc_name) {
+ modules[0] = NULL;
+ *needed = sizeof(gpointer);
+ return TRUE;
+ }
+
+ mods = mono_w32process_get_modules (pid);
+ if (!mods) {
+ modules[0] = NULL;
+ *needed = sizeof(gpointer);
+ g_free (proc_name);
+ return TRUE;
+ }
+
+ count = g_slist_length (mods);
+
+ /* count + 1 to leave slot 0 for the main module */
+ *needed = sizeof(gpointer) * (count + 1);
+
+ /*
+ * Use the NULL shortcut, as the first line in
+ * /proc/<pid>/maps isn't the executable, and we need
+ * that first in the returned list. Check the module name
+ * to see if it ends with the proc name and substitute
+ * the first entry with it. FIXME if this turns out to
+ * be a problem.
+ */
+ modules[0] = NULL;
+ for (i = 0; i < (avail - 1) && i < count; i++) {
+ module = (MonoW32ProcessModule *)g_slist_nth_data (mods, i);
+ if (modules[0] != NULL)
+ modules[i] = module->address_start;
+ else if (match_procname_to_modulename (proc_name, module->filename))
+ modules[0] = module->address_start;
+ else
+ modules[i + 1] = module->address_start;
+ }
+
+ for (i = 0; i < count; i++) {
+ mono_w32process_module_free ((MonoW32ProcessModule *)g_slist_nth_data (mods, i));
+ }
+ g_slist_free (mods);
+ g_free (proc_name);
+
+ return TRUE;
+}
+
+guint32
+mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ gint pid, len;
+ gsize bytes;
+ gchar *path;
+ gunichar2 *proc_path;
+
+ size *= sizeof (gunichar2); /* adjust for unicode characters */
+
+ if (basename == NULL || size == 0)
+ return 0;
+
+ pid = mono_w32process_get_pid (process);
+
+ path = mono_w32process_get_path (pid);
+ if (path == NULL)
+ return 0;
+
+ proc_path = mono_unicode_from_external (path, &bytes);
+ g_free (path);
+
+ if (proc_path == NULL)
+ return 0;
+
+ len = (bytes / 2);
+
+ /* Add the terminator */
+ bytes += 2;
+
+ if (size < bytes) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
+ memcpy (basename, proc_path, size);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)", __func__, size, bytes);
+ memcpy (basename, proc_path, bytes);
+ }
+
+ g_free (proc_path);
+
+ return len;
+}
+
+guint32
+mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ MonoW32HandleProcess *process_handle;
+ pid_t pid;
+ gunichar2 *procname;
+ char *procname_ext = NULL;
+ glong len;
+ gsize bytes;
+ GSList *mods = NULL;
+ MonoW32ProcessModule *found_module;
+ guint32 count;
+ int i;
+ char *proc_name = NULL;
+ gboolean res;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module base name, process handle %p module %p",
+ __func__, process, module);
+
+ size = size * sizeof (gunichar2); /* adjust for unicode characters */
+
+ if (basename == NULL || size == 0)
+ return 0;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (process);
+ proc_name = mono_w32process_get_name (pid);
+ } else {
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return 0;
+ }
+
+ pid = process_handle->id;
+ proc_name = g_strdup (process_handle->proc_name);
+ }
+
+ mods = mono_w32process_get_modules (pid);
+ if (!mods) {
+ g_free (proc_name);
+ return 0;
+ }
+
+ count = g_slist_length (mods);
+
+ /* If module != NULL compare the address.
+ * If module == NULL we are looking for the main module.
+ * The best we can do for now check it the module name end with the process name.
+ */
+ for (i = 0; i < count; i++) {
+ found_module = (MonoW32ProcessModule *)g_slist_nth_data (mods, i);
+ if (procname_ext == NULL &&
+ ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+ (module != NULL && found_module->address_start == module))) {
+ procname_ext = g_path_get_basename (found_module->filename);
+ }
+
+ mono_w32process_module_free (found_module);
+ }
+
+ if (procname_ext == NULL) {
+ /* If it's *still* null, we might have hit the
+ * case where reading /proc/$pid/maps gives an
+ * empty file for this user.
+ */
+ procname_ext = mono_w32process_get_name (pid);
+ }
+
+ g_slist_free (mods);
+ g_free (proc_name);
+
+ if (procname_ext) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Process name is [%s]", __func__,
+ procname_ext);
+
+ procname = mono_unicode_from_external (procname_ext, &bytes);
+ if (procname == NULL) {
+ /* bugger */
+ g_free (procname_ext);
+ return 0;
+ }
+
+ len = (bytes / 2);
+
+ /* Add the terminator */
+ bytes += 2;
+
+ if (size < bytes) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
+
+ memcpy (basename, procname, size);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
+ __func__, size, bytes);
+
+ memcpy (basename, procname, bytes);
+ }
+
+ g_free (procname);
+ g_free (procname_ext);
+
+ return len;
+ }
+
+ return 0;
+}
+
+gboolean
+mono_w32process_module_get_information (gpointer process, gpointer module, WapiModuleInfo *modinfo, guint32 size)
+{
+ MonoW32HandleProcess *process_handle;
+ pid_t pid;
+ GSList *mods = NULL;
+ MonoW32ProcessModule *found_module;
+ guint32 count;
+ int i;
+ gboolean ret = FALSE;
+ char *proc_name = NULL;
+ gboolean res;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module info, process handle %p module %p",
+ __func__, process, module);
+
+ if (modinfo == NULL || size < sizeof (WapiModuleInfo))
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+ pid = (pid_t)WAPI_HANDLE_TO_PID (process);
+ proc_name = mono_w32process_get_name (pid);
+ } else {
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ proc_name = g_strdup (process_handle->proc_name);
+ }
+
+ mods = mono_w32process_get_modules (pid);
+ if (!mods) {
+ g_free (proc_name);
+ return FALSE;
+ }
+
+ count = g_slist_length (mods);
+
+ /* If module != NULL compare the address.
+ * If module == NULL we are looking for the main module.
+ * The best we can do for now check it the module name end with the process name.
+ */
+ for (i = 0; i < count; i++) {
+ found_module = (MonoW32ProcessModule *)g_slist_nth_data (mods, i);
+ if (ret == FALSE &&
+ ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+ (module != NULL && found_module->address_start == module))) {
+ modinfo->lpBaseOfDll = found_module->address_start;
+ modinfo->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start);
+ modinfo->EntryPoint = found_module->address_offset;
+ ret = TRUE;
+ }
+
+ mono_w32process_module_free (found_module);
+ }
+
+ g_slist_free (mods);
+ g_free (proc_name);
+
+ return ret;
+}
+
+static void
+switch_dir_separators (char *path)
+{
+ size_t i, pathLength = strlen(path);
+
+ /* Turn all the slashes round the right way, except for \' */
+ /* There are probably other characters that need to be excluded as well. */
+ for (i = 0; i < pathLength; i++) {
+ if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' )
+ path[i] = '/';
+ }
+}
+
+#if HAVE_SIGACTION
+
+MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context))
+{
+ int status;
+ int pid;
+ MonoProcess *p;
+
+ do {
+ do {
+ pid = waitpid (-1, &status, WNOHANG);
+ } while (pid == -1 && errno == EINTR);
+
+ if (pid <= 0)
+ break;
+
+ /*
+ * This can run concurrently with the code in the rest of this module.
+ */
+ for (p = mono_processes; p; p = p->next) {
+ if (p->pid == pid) {
+ break;
+ }
+ }
+ if (p) {
+ p->pid = 0; /* this pid doesn't exist anymore, clear it */
+ p->status = status;
+ mono_os_sem_post (&p->exit_sem);
+ mono_memory_barrier ();
+ /* Mark this as freeable, the pointer becomes invalid afterwards */
+ p->freeable = TRUE;
+ }
+ } while (1);
+}
+
+static void
+process_add_sigchld_handler (void)
+{
+ struct sigaction sa;
+
+ sa.sa_sigaction = mono_sigchld_signal_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
+ g_assert (sigaction (SIGCHLD, &sa, NULL) != -1);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "Added SIGCHLD handler");
+}
+
+#endif
+
+static gboolean
+is_readable_or_executable (const char *prog)
+{
+ struct stat buf;
+ int a = access (prog, R_OK);
+ int b = access (prog, X_OK);
+ if (a != 0 && b != 0)
+ return FALSE;
+ if (stat (prog, &buf))
+ return FALSE;
+ if (S_ISREG (buf.st_mode))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+is_executable (const char *prog)
+{
+ struct stat buf;
+ if (access (prog, X_OK) != 0)
+ return FALSE;
+ if (stat (prog, &buf))
+ return FALSE;
+ if (S_ISREG (buf.st_mode))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+is_managed_binary (const char *filename)
+{
+ int original_errno = errno;
+#if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE)
+ int file = open (filename, O_RDONLY | O_LARGEFILE);
+#else
+ int file = open (filename, O_RDONLY);
+#endif
+ off_t new_offset;
+ unsigned char buffer[8];
+ off_t file_size, optional_header_offset;
+ off_t pe_header_offset, clr_header_offset;
+ gboolean managed = FALSE;
+ int num_read;
+ guint32 first_word, second_word, magic_number;
+
+ /* If we are unable to open the file, then we definitely
+ * can't say that it is managed. The child mono process
+ * probably wouldn't be able to open it anyway.
+ */
+ if (file < 0) {
+ errno = original_errno;
+ return FALSE;
+ }
+
+ /* Retrieve the length of the file for future sanity checks. */
+ file_size = lseek (file, 0, SEEK_END);
+ lseek (file, 0, SEEK_SET);
+
+ /* We know we need to read a header field at offset 60. */
+ if (file_size < 64)
+ goto leave;
+
+ num_read = read (file, buffer, 2);
+
+ if ((num_read != 2) || (buffer[0] != 'M') || (buffer[1] != 'Z'))
+ goto leave;
+
+ new_offset = lseek (file, 60, SEEK_SET);
+
+ if (new_offset != 60)
+ goto leave;
+
+ num_read = read (file, buffer, 4);
+
+ if (num_read != 4)
+ goto leave;
+ pe_header_offset = buffer[0]
+ | (buffer[1] << 8)
+ | (buffer[2] << 16)
+ | (buffer[3] << 24);
+
+ if (pe_header_offset + 24 > file_size)
+ goto leave;
+
+ new_offset = lseek (file, pe_header_offset, SEEK_SET);
+
+ if (new_offset != pe_header_offset)
+ goto leave;
+
+ num_read = read (file, buffer, 4);
+
+ if ((num_read != 4) || (buffer[0] != 'P') || (buffer[1] != 'E') || (buffer[2] != 0) || (buffer[3] != 0))
+ goto leave;
+
+ /*
+ * Verify that the header we want in the optional header data
+ * is present in this binary.
+ */
+ new_offset = lseek (file, pe_header_offset + 20, SEEK_SET);
+
+ if (new_offset != pe_header_offset + 20)
+ goto leave;
+
+ num_read = read (file, buffer, 2);
+
+ if ((num_read != 2) || ((buffer[0] | (buffer[1] << 8)) < 216))
+ goto leave;
+
+ optional_header_offset = pe_header_offset + 24;
+
+ /* Read the PE magic number */
+ new_offset = lseek (file, optional_header_offset, SEEK_SET);
+
+ if (new_offset != optional_header_offset)
+ goto leave;
+
+ num_read = read (file, buffer, 2);
+
+ if (num_read != 2)
+ goto leave;
+
+ magic_number = (buffer[0] | (buffer[1] << 8));
+
+ if (magic_number == 0x10B) // PE32
+ clr_header_offset = 208;
+ else if (magic_number == 0x20B) // PE32+
+ clr_header_offset = 224;
+ else
+ goto leave;
+
+ /* Read the CLR header address and size fields. These will be
+ * zero if the binary is not managed.
+ */
+ new_offset = lseek (file, optional_header_offset + clr_header_offset, SEEK_SET);
+
+ if (new_offset != optional_header_offset + clr_header_offset)
+ goto leave;
+
+ num_read = read (file, buffer, 8);
+
+ /* We are not concerned with endianness, only with
+ * whether it is zero or not.
+ */
+ first_word = *(guint32 *)&buffer[0];
+ second_word = *(guint32 *)&buffer[4];
+
+ if ((num_read != 8) || (first_word == 0) || (second_word == 0))
+ goto leave;
+
+ managed = TRUE;
+
+leave:
+ close (file);
+ errno = original_errno;
+ return managed;
+}
+
+static gboolean
+process_create (const gunichar2 *appname, const gunichar2 *cmdline, gpointer new_environ,
+ const gunichar2 *cwd, StartupHandles *startup_handles, MonoW32ProcessInfo *process_info)
+{
+#if defined (HAVE_FORK) && defined (HAVE_EXECVE)
+ char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL;
+ char *dir = NULL, **env_strings = NULL, **argv = NULL;
+ guint32 i, env_count = 0;
+ gboolean ret = FALSE;
+ gpointer handle = NULL;
+ MonoW32HandleProcess process_handle = {0}, *process_handle_data;
+ GError *gerr = NULL;
+ int in_fd, out_fd, err_fd;
+ pid_t pid = 0;
+ int startup_pipe [2] = {-1, -1};
+ int dummy;
+ MonoProcess *mono_process;
+ gboolean fork_failed = FALSE;
+ gboolean res;
+
+#if HAVE_SIGACTION
+ mono_lazy_initialize (&process_sig_chld_once, process_add_sigchld_handler);
+#endif
+
+ /* appname and cmdline specify the executable and its args:
+ *
+ * If appname is not NULL, it is the name of the executable.
+ * Otherwise the executable is the first token in cmdline.
+ *
+ * Executable searching:
+ *
+ * If appname is not NULL, it can specify the full path and
+ * file name, or else a partial name and the current directory
+ * will be used. There is no additional searching.
+ *
+ * If appname is NULL, the first whitespace-delimited token in
+ * cmdline is used. If the name does not contain a full
+ * directory path, the search sequence is:
+ *
+ * 1) The directory containing the current process
+ * 2) The current working directory
+ * 3) The windows system directory (Ignored)
+ * 4) The windows directory (Ignored)
+ * 5) $PATH
+ *
+ * Just to make things more interesting, tokens can contain
+ * white space if they are surrounded by quotation marks. I'm
+ * beginning to understand just why windows apps are generally
+ * so crap, with an API like this :-(
+ */
+ if (appname != NULL) {
+ cmd = mono_unicode_to_external (appname);
+ if (cmd == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL",
+ __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+
+ switch_dir_separators(cmd);
+ }
+
+ if (cmdline != NULL) {
+ args = mono_unicode_to_external (cmdline);
+ if (args == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+ }
+
+ if (cwd != NULL) {
+ dir = mono_unicode_to_external (cwd);
+ if (dir == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+
+ /* Turn all the slashes round the right way */
+ switch_dir_separators(dir);
+ }
+
+
+ /* We can't put off locating the executable any longer :-( */
+ if (cmd != NULL) {
+ char *unquoted;
+ if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) {
+ /* Strip off the drive letter. I can't
+ * believe that CP/M holdover is still
+ * visible...
+ */
+ g_memmove (cmd, cmd+2, strlen (cmd)-2);
+ cmd[strlen (cmd)-2] = '\0';
+ }
+
+ unquoted = g_shell_unquote (cmd, NULL);
+ if (unquoted[0] == '/') {
+ /* Assume full path given */
+ prog = g_strdup (unquoted);
+
+ /* Executable existing ? */
+ if (!is_readable_or_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
+ __func__, prog);
+ g_free (unquoted);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ } else {
+ /* Search for file named by cmd in the current
+ * directory
+ */
+ char *curdir = g_get_current_dir ();
+
+ prog = g_strdup_printf ("%s/%s", curdir, unquoted);
+ g_free (curdir);
+
+ /* And make sure it's readable */
+ if (!is_readable_or_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
+ __func__, prog);
+ g_free (unquoted);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ }
+ g_free (unquoted);
+
+ args_after_prog = args;
+ } else {
+ char *token = NULL;
+ char quote;
+
+ /* Dig out the first token from args, taking quotation
+ * marks into account
+ */
+
+ /* First, strip off all leading whitespace */
+ args = g_strchug (args);
+
+ /* args_after_prog points to the contents of args
+ * after token has been set (otherwise argv[0] is
+ * duplicated)
+ */
+ args_after_prog = args;
+
+ /* Assume the opening quote will always be the first
+ * character
+ */
+ if (args[0] == '\"' || args [0] == '\'') {
+ quote = args [0];
+ for (i = 1; args[i] != '\0' && args[i] != quote; i++);
+ if (args [i + 1] == '\0' || g_ascii_isspace (args[i+1])) {
+ /* We found the first token */
+ token = g_strndup (args+1, i-1);
+ args_after_prog = g_strchug (args + i + 1);
+ } else {
+ /* Quotation mark appeared in the
+ * middle of the token. Just give the
+ * whole first token, quotes and all,
+ * to exec.
+ */
+ }
+ }
+
+ if (token == NULL) {
+ /* No quote mark, or malformed */
+ for (i = 0; args[i] != '\0'; i++) {
+ if (g_ascii_isspace (args[i])) {
+ token = g_strndup (args, i);
+ args_after_prog = args + i + 1;
+ break;
+ }
+ }
+ }
+
+ if (token == NULL && args[0] != '\0') {
+ /* Must be just one token in the string */
+ token = g_strdup (args);
+ args_after_prog = NULL;
+ }
+
+ if (token == NULL) {
+ /* Give up */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find what to exec", __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+
+ /* Turn all the slashes round the right way. Only for
+ * the prg. name
+ */
+ switch_dir_separators(token);
+
+ if (g_ascii_isalpha (token[0]) && (token[1] == ':')) {
+ /* Strip off the drive letter. I can't
+ * believe that CP/M holdover is still
+ * visible...
+ */
+ g_memmove (token, token+2, strlen (token)-2);
+ token[strlen (token)-2] = '\0';
+ }
+
+ if (token[0] == '/') {
+ /* Assume full path given */
+ prog = g_strdup (token);
+
+ /* Executable existing ? */
+ if (!is_readable_or_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
+ __func__, token);
+ g_free (token);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ } else {
+ char *curdir = g_get_current_dir ();
+
+ /* FIXME: Need to record the directory
+ * containing the current process, and check
+ * that for the new executable as the first
+ * place to look
+ */
+
+ prog = g_strdup_printf ("%s/%s", curdir, token);
+ g_free (curdir);
+
+ /* I assume X_OK is the criterion to use,
+ * rather than F_OK
+ *
+ * X_OK is too strict *if* the target is a CLR binary
+ */
+ if (!is_readable_or_executable (prog)) {
+ g_free (prog);
+ prog = g_find_program_in_path (token);
+ if (prog == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s", __func__, token);
+
+ g_free (token);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ }
+ }
+
+ g_free (token);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Exec prog [%s] args [%s]",
+ __func__, prog, args_after_prog);
+
+ /* Check for CLR binaries; if found, we will try to invoke
+ * them using the same mono binary that started us.
+ */
+ if (is_managed_binary (prog)) {
+ gunichar2 *newapp, *newcmd;
+ gsize bytes_ignored;
+
+ newapp = mono_unicode_from_external (cli_launcher ? cli_launcher : "mono", &bytes_ignored);
+ if (newapp) {
+ if (appname)
+ newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space, appname, utf16_space, cmdline, NULL);
+ else
+ newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space, cmdline, NULL);
+
+ g_free (newapp);
+
+ if (newcmd) {
+ ret = process_create (NULL, newcmd, new_environ, cwd, startup_handles, process_info);
+
+ g_free (newcmd);
+
+ goto free_strings;
+ }
+ }
+ } else {
+ if (!is_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Executable permisson not set on %s", __func__, prog);
+ SetLastError (ERROR_ACCESS_DENIED);
+ goto free_strings;
+ }
+ }
+
+ if (args_after_prog != NULL && *args_after_prog) {
+ char *qprog;
+
+ qprog = g_shell_quote (prog);
+ full_prog = g_strconcat (qprog, " ", args_after_prog, NULL);
+ g_free (qprog);
+ } else {
+ full_prog = g_shell_quote (prog);
+ }
+
+ ret = g_shell_parse_argv (full_prog, NULL, &argv, &gerr);
+ if (ret == FALSE) {
+ g_message ("process_create: %s\n", gerr->message);
+ g_error_free (gerr);
+ gerr = NULL;
+ goto free_strings;
+ }
+
+ if (startup_handles) {
+ in_fd = GPOINTER_TO_UINT (startup_handles->input);
+ out_fd = GPOINTER_TO_UINT (startup_handles->output);
+ err_fd = GPOINTER_TO_UINT (startup_handles->error);
+ } else {
+ in_fd = GPOINTER_TO_UINT (GetStdHandle (STD_INPUT_HANDLE));
+ out_fd = GPOINTER_TO_UINT (GetStdHandle (STD_OUTPUT_HANDLE));
+ err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
+ }
+
+ process_handle.proc_name = g_strdup (prog);
+
+ process_set_defaults (&process_handle);
+
+ handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating process handle", __func__);
+
+ ret = FALSE;
+ SetLastError (ERROR_OUTOFMEMORY);
+ goto free_strings;
+ }
+
+ /* new_environ is a block of NULL-terminated strings, which
+ * is itself NULL-terminated. Of course, passing an array of
+ * string pointers would have made things too easy :-(
+ *
+ * If new_environ is not NULL it specifies the entire set of
+ * environment variables in the new process. Otherwise the
+ * new process inherits the same environment.
+ */
+ if (new_environ) {
+ gunichar2 *new_environp;
+
+ /* Count the number of strings */
+ for (new_environp = (gunichar2 *)new_environ; *new_environp; new_environp++) {
+ env_count++;
+ while (*new_environp)
+ new_environp++;
+ }
+
+ /* +2: one for the process handle value, and the last
+ * one is NULL
+ */
+ env_strings = g_new0 (char *, env_count + 2);
+
+ /* Copy each environ string into 'strings' turning it
+ * into utf8 (or the requested encoding) at the same
+ * time
+ */
+ env_count = 0;
+ for (new_environp = (gunichar2 *)new_environ; *new_environp; new_environp++) {
+ env_strings[env_count] = mono_unicode_to_external (new_environp);
+ env_count++;
+ while (*new_environp) {
+ new_environp++;
+ }
+ }
+ } else {
+ for (i = 0; environ[i] != NULL; i++)
+ env_count++;
+
+ /* +2: one for the process handle value, and the last
+ * one is NULL
+ */
+ env_strings = g_new0 (char *, env_count + 2);
+
+ /* Copy each environ string into 'strings' turning it
+ * into utf8 (or the requested encoding) at the same
+ * time
+ */
+ env_count = 0;
+ for (i = 0; environ[i] != NULL; i++) {
+ env_strings[env_count] = g_strdup (environ[i]);
+ env_count++;
+ }
+ }
+
+ /* Create a pipe to make sure the child doesn't exit before
+ * we can add the process to the linked list of mono_processes */
+ if (pipe (startup_pipe) == -1) {
+ /* Could not create the pipe to synchroniz process startup. We'll just not synchronize.
+ * This is just for a very hard to hit race condition in the first place */
+ startup_pipe [0] = startup_pipe [1] = -1;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__);
+ }
+
+ switch (pid = fork ()) {
+ case -1: /* Error */ {
+ SetLastError (ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ fork_failed = TRUE;
+ break;
+ }
+ case 0: /* Child */ {
+ if (startup_pipe [0] != -1) {
+ /* Wait until the parent has updated it's internal data */
+ ssize_t _i G_GNUC_UNUSED = read (startup_pipe [0], &dummy, 1);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: child: parent has completed its setup", __func__);
+ close (startup_pipe [0]);
+ close (startup_pipe [1]);
+ }
+
+ /* should we detach from the process group? */
+
+ /* Connect stdin, stdout and stderr */
+ dup2 (in_fd, 0);
+ dup2 (out_fd, 1);
+ dup2 (err_fd, 2);
+
+ /* Close all file descriptors */
+ for (i = mono_w32handle_fd_reserve - 1; i > 2; i--)
+ close (i);
+
+#ifdef DEBUG_ENABLED
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: exec()ing [%s] in dir [%s]", __func__, cmd,
+ dir == NULL?".":dir);
+ for (i = 0; argv[i] != NULL; i++)
+ g_message ("arg %d: [%s]", i, argv[i]);
+
+ for (i = 0; env_strings[i] != NULL; i++)
+ g_message ("env %d: [%s]", i, env_strings[i]);
+#endif
+
+ /* set cwd */
+ if (dir != NULL && chdir (dir) == -1) {
+ /* set error */
+ _exit (-1);
+ }
+
+ /* exec */
+ execve (argv[0], argv, env_strings);
+
+ /* set error */
+ _exit (-1);
+
+ break;
+ }
+ default: /* Parent */ {
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle_data);
+ if (!res) {
+ g_warning ("%s: error looking up process handle %p", __func__, handle);
+ mono_w32handle_unref (handle);
+ } else {
+ process_handle_data->id = pid;
+
+ /* Add our mono_process into the linked list of mono_processes */
+ mono_process = (MonoProcess *) g_malloc0 (sizeof (MonoProcess));
+ mono_process->pid = pid;
+ mono_process->handle_count = 1;
+ mono_os_sem_init (&mono_process->exit_sem, 0);
+
+ /* 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;
+
+ 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->process_handle = handle;
+ process_info->pid = pid;
+
+ /* FIXME: we might need to handle the thread info some day */
+ process_info->thread_handle = INVALID_HANDLE_VALUE;
+ process_info->tid = 0;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (fork_failed)
+ mono_w32handle_unref (handle);
+
+ if (startup_pipe [1] != -1) {
+ /* Write 1 byte, doesn't matter what */
+ ssize_t _i G_GNUC_UNUSED = write (startup_pipe [1], startup_pipe, 1);
+ close (startup_pipe [0]);
+ close (startup_pipe [1]);
+ }
+
+free_strings:
+ if (cmd)
+ g_free (cmd);
+ if (full_prog)
+ g_free (full_prog);
+ if (prog)
+ g_free (prog);
+ if (args)
+ g_free (args);
+ if (dir)
+ g_free (dir);
+ if (env_strings)
+ g_strfreev (env_strings);
+ if (argv)
+ g_strfreev (argv);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p for pid %d", __func__, handle, pid);
+
+ /* Check if something needs to be cleaned up. */
+ processes_cleanup ();
+
+ return ret;
+#else
+ SetLastError (ERROR_NOT_SUPPORTED);
+ return FALSE;
+#endif // defined (HAVE_FORK) && defined (HAVE_EXECVE)
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_info)
+{
+ const gunichar2 *lpFile;
+ const gunichar2 *lpParameters;
+ const gunichar2 *lpDirectory;
+ gunichar2 *args;
+ gboolean ret;
+
+ if (!proc_start_info->filename) {
+ /* w2k returns TRUE for this, for some reason. */
+ ret = TRUE;
+ goto done;
+ }
+
+ lpFile = proc_start_info->filename ? mono_string_chars (proc_start_info->filename) : NULL;
+ lpParameters = proc_start_info->arguments ? mono_string_chars (proc_start_info->arguments) : NULL;
+ lpDirectory = proc_start_info->working_directory && mono_string_length (proc_start_info->working_directory) != 0 ?
+ mono_string_chars (proc_start_info->working_directory) : NULL;
+
+ /* Put both executable and parameters into the second argument
+ * to process_create (), so it searches $PATH. The conversion
+ * into and back out of utf8 is because there is no
+ * g_strdup_printf () equivalent for gunichar2 :-(
+ */
+ args = utf16_concat (utf16_quote, lpFile, utf16_quote, lpParameters == NULL ? NULL : utf16_space, lpParameters, NULL);
+ if (args == NULL) {
+ SetLastError (ERROR_INVALID_DATA);
+ ret = FALSE;
+ goto done;
+ }
+ ret = process_create (NULL, args, NULL, lpDirectory, NULL, process_info);
+ g_free (args);
+
+ if (!ret && GetLastError () == ERROR_OUTOFMEMORY)
+ goto done;
+
+ if (!ret) {
+ static char *handler;
+ static gunichar2 *handler_utf16;
+
+ if (handler_utf16 == (gunichar2 *)-1) {
+ ret = FALSE;
+ goto done;
+ }
+
+#ifdef PLATFORM_MACOSX
+ handler = g_strdup ("/usr/bin/open");
+#else
+ /*
+ * On Linux, try: xdg-open, the FreeDesktop standard way of doing it,
+ * if that fails, try to use gnome-open, then kfmclient
+ */
+ handler = g_find_program_in_path ("xdg-open");
+ if (handler == NULL){
+ handler = g_find_program_in_path ("gnome-open");
+ if (handler == NULL){
+ handler = g_find_program_in_path ("kfmclient");
+ if (handler == NULL){
+ handler_utf16 = (gunichar2 *) -1;
+ ret = FALSE;
+ goto done;
+ } else {
+ /* kfmclient needs exec argument */
+ char *old = handler;
+ handler = g_strconcat (old, " exec",
+ NULL);
+ g_free (old);
+ }
+ }
+ }
+#endif
+ handler_utf16 = g_utf8_to_utf16 (handler, -1, NULL, NULL, NULL);
+ g_free (handler);
+
+ /* Put quotes around the filename, in case it's a url
+ * that contains #'s (process_create() calls
+ * g_shell_parse_argv(), which deliberately throws
+ * away anything after an unquoted #). Fixes bug
+ * 371567.
+ */
+ args = utf16_concat (handler_utf16, utf16_space, utf16_quote, lpFile, utf16_quote,
+ lpParameters == NULL ? NULL : utf16_space, lpParameters, NULL);
+ if (args == NULL) {
+ SetLastError (ERROR_INVALID_DATA);
+ ret = FALSE;
+ goto done;
+ }
+ ret = process_create (NULL, args, NULL, lpDirectory, NULL, process_info);
+ g_free (args);
+ if (!ret) {
+ if (GetLastError () != ERROR_OUTOFMEMORY)
+ SetLastError (ERROR_INVALID_DATA);
+ ret = FALSE;
+ goto done;
+ }
+ /* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */
+ CloseHandle (process_info->process_handle);
+ process_info->process_handle = NULL;
+ }
+
+done:
+ if (ret == FALSE) {
+ process_info->pid = -GetLastError ();
+ } else {
+ process_info->thread_handle = NULL;
+#if !defined(MONO_CROSS_COMPILE)
+ process_info->pid = mono_w32process_get_pid (process_info->process_handle);
+#else
+ process_info->pid = 0;
+#endif
+ process_info->tid = 0;
+ }
+
+ return ret;
+}
+
+/* Only used when UseShellExecute is false */
+static gboolean
+process_get_complete_path (const gunichar2 *appname, gchar **completed)
+{
+ gchar *utf8app;
+ gchar *found;
+
+ utf8app = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
+
+ if (g_path_is_absolute (utf8app)) {
+ *completed = g_shell_quote (utf8app);
+ g_free (utf8app);
+ return TRUE;
+ }
+
+ if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
+ *completed = g_shell_quote (utf8app);
+ g_free (utf8app);
+ return TRUE;
+ }
+
+ found = g_find_program_in_path (utf8app);
+ if (found == NULL) {
+ *completed = NULL;
+ g_free (utf8app);
+ return FALSE;
+ }
+
+ *completed = g_shell_quote (found);
+ g_free (found);
+ g_free (utf8app);
+ return TRUE;
+}
+
+static gboolean
+process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
+{
+ gchar *spath = NULL;
+
+ *shell_path = NULL;
+ *cmd = proc_start_info->arguments;
+
+ process_get_complete_path (mono_string_chars (proc_start_info->filename), &spath);
+ if (spath != NULL) {
+ *shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
+ g_free (spath);
+ }
+
+ return (*shell_path != NULL) ? TRUE : FALSE;
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfo *proc_start_info,
+ HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoW32ProcessInfo *process_info)
+{
+ gboolean ret;
+ gunichar2 *dir;
+ StartupHandles startup_handles;
+ gunichar2 *shell_path = NULL;
+ gchar *env_vars = NULL;
+ MonoString *cmd = NULL;
+
+ memset (&startup_handles, 0, sizeof (startup_handles));
+ startup_handles.input = stdin_handle;
+ startup_handles.output = stdout_handle;
+ startup_handles.error = stderr_handle;
+
+ if (process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
+ process_info->pid = -ERROR_FILE_NOT_FOUND;
+ return FALSE;
+ }
+
+ if (process_info->env_keys) {
+ gint i, len;
+ MonoString *ms;
+ MonoString *key, *value;
+ gunichar2 *str, *ptr;
+ gunichar2 *equals16;
+
+ for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ ms = mono_array_get (process_info->env_values, MonoString *, i);
+ if (ms == NULL)
+ continue;
+
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ ms = mono_array_get (process_info->env_keys, MonoString *, i);
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ len += 2 * sizeof (gunichar2);
+ }
+
+ equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
+ ptr = str = g_new0 (gunichar2, len + 1);
+ for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ value = mono_array_get (process_info->env_values, MonoString *, i);
+ if (value == NULL)
+ continue;
+
+ key = mono_array_get (process_info->env_keys, MonoString *, i);
+ memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
+ ptr += mono_string_length (key);
+
+ memcpy (ptr, equals16, sizeof (gunichar2));
+ ptr++;
+
+ memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
+ ptr += mono_string_length (value);
+ ptr++;
+ }
+
+ g_free (equals16);
+ env_vars = (gchar *) str;
+ }
+
+ /* The default dir name is "". Turn that into NULL to mean "current directory" */
+ dir = proc_start_info->working_directory && mono_string_length (proc_start_info->working_directory) > 0 ?
+ mono_string_chars (proc_start_info->working_directory) : NULL;
+
+ ret = process_create (shell_path, cmd ? mono_string_chars (cmd): NULL, env_vars, dir, &startup_handles, process_info);
+
+ g_free (env_vars);
+ if (shell_path != NULL)
+ g_free (shell_path);
+
+ if (!ret)
+ process_info->pid = -GetLastError ();
+
+ return ret;
+}
+
+/* Returns an array of pids */
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
+{
+ MonoError error;
+ MonoArray *procs;
+ gpointer *pidarray;
+ int i, count;
+
+ pidarray = mono_process_list (&count);
+ if (!pidarray) {
+ mono_set_pending_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses"));
+ return NULL;
+ }
+ procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
+ if (mono_error_set_pending_exception (&error)) {
+ g_free (pidarray);
+ return NULL;
+ }
+ if (sizeof (guint32) == sizeof (gpointer)) {
+ memcpy (mono_array_addr (procs, guint32, 0), pidarray, count * sizeof (gint32));
+ } else {
+ for (i = 0; i < count; ++i)
+ *(mono_array_addr (procs, guint32, i)) = GPOINTER_TO_UINT (pidarray [i]);
+ }
+ g_free (pidarray);
+
+ return procs;
+}
+
+void
+mono_w32process_set_cli_launcher (gchar *path)
+{
+ g_free (cli_launcher);
+ cli_launcher = g_strdup (path);
+}
+
+gpointer
+ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
+{
+ mono_w32handle_ref (current_process);
+ return current_process;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
+{
+ MonoW32HandleProcess *process_handle;
+ guint32 pid;
+ gboolean res;
+
+ if (!exitcode)
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ pid = WAPI_HANDLE_TO_PID (handle);
+ /* This is a pseudo handle, so we don't know what the exit
+ * code was, but we can check whether it's alive or not */
+ if (is_pid_valid (pid)) {
+ *exitcode = STILL_ACTIVE;
+ return TRUE;
+ } else {
+ *exitcode = -1;
+ return TRUE;
+ }
+ }
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ if (process_handle->id == wapi_getpid ()) {
+ *exitcode = STILL_ACTIVE;
+ return TRUE;
+ }
+
+ /* A process handle is only signalled if the process has exited
+ * and has been waited for. Make sure any process exit has been
+ * noticed before checking if the process is signalled.
+ * Fixes bug 325463. */
+ mono_w32handle_wait_one (handle, 0, TRUE);
+
+ *exitcode = mono_w32handle_issignalled (handle) ? process_handle->exitstatus : STILL_ACTIVE;
+ return TRUE;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
+{
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
+ return TRUE;
+ return CloseHandle (handle);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
+{
+#ifdef HAVE_KILL
+ MonoW32HandleProcess *process_handle;
+ int ret;
+ pid_t pid;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
+ } else {
+ gboolean res;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ }
+
+ ret = kill (pid, exitcode == -1 ? SIGKILL : SIGTERM);
+ if (ret == 0)
+ return TRUE;
+
+ switch (errno) {
+ case EINVAL: SetLastError (ERROR_INVALID_PARAMETER); break;
+ case EPERM: SetLastError (ERROR_ACCESS_DENIED); break;
+ case ESRCH: SetLastError (ERROR_PROC_NOT_FOUND); break;
+ default: SetLastError (ERROR_GEN_FAILURE); break;
+ }
+
+ return FALSE;
+#else
+ g_error ("kill() is not supported by this platform");
+#endif
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
+{
+ MonoW32HandleProcess *process_handle;
+ gboolean res;
+
+ if (!min || !max)
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
+ return FALSE;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ *min = process_handle->min_working_set;
+ *max = process_handle->max_working_set;
+ return TRUE;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
+{
+ MonoW32HandleProcess *process_handle;
+ gboolean res;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
+ return FALSE;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ process_handle->min_working_set = min;
+ process_handle->max_working_set = max;
+ return TRUE;
+}
+
+gint32
+ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
+{
+#ifdef HAVE_GETPRIORITY
+ MonoW32HandleProcess *process_handle;
+ gint ret;
+ pid_t pid;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
+ } else {
+ gboolean res;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
+ pid = process_handle->id;
+ }
+
+ errno = 0;
+ ret = getpriority (PRIO_PROCESS, pid);
+ if (ret == -1 && errno != 0) {
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ SetLastError (ERROR_ACCESS_DENIED);
+ break;
+ case ESRCH:
+ SetLastError (ERROR_PROC_NOT_FOUND);
+ break;
+ default:
+ SetLastError (ERROR_GEN_FAILURE);
+ }
+ return 0;
+ }
+
+ if (ret == 0)
+ return MONO_W32PROCESS_PRIORITY_CLASS_NORMAL;
+ else if (ret < -15)
+ return MONO_W32PROCESS_PRIORITY_CLASS_REALTIME;
+ else if (ret < -10)
+ return MONO_W32PROCESS_PRIORITY_CLASS_HIGH;
+ else if (ret < 0)
+ return MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
+ else if (ret > 10)
+ return MONO_W32PROCESS_PRIORITY_CLASS_IDLE;
+ else if (ret > 0)
+ return MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
+
+ return MONO_W32PROCESS_PRIORITY_CLASS_NORMAL;
+#else
+ SetLastError (ERROR_NOT_SUPPORTED);
+ return 0;
+#endif
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
+{
+#ifdef HAVE_SETPRIORITY
+ MonoW32HandleProcess *process_handle;
+ int ret;
+ int prio;
+ pid_t pid;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
+ } else {
+ gboolean res;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ }
+
+ switch (priorityClass) {
+ case MONO_W32PROCESS_PRIORITY_CLASS_IDLE:
+ prio = 19;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
+ prio = 10;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_NORMAL:
+ prio = 0;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
+ prio = -5;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_HIGH:
+ prio = -11;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_REALTIME:
+ prio = -20;
+ break;
+ default:
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ ret = setpriority (PRIO_PROCESS, pid, prio);
+ if (ret == -1) {
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ SetLastError (ERROR_ACCESS_DENIED);
+ break;
+ case ESRCH:
+ SetLastError (ERROR_PROC_NOT_FOUND);
+ break;
+ default:
+ SetLastError (ERROR_GEN_FAILURE);
+ }
+ }
+
+ return ret == 0;
+#else
+ SetLastError (ERROR_NOT_SUPPORTED);
+ return FALSE;
+#endif
+}
+
+static void
+ticks_to_processtime (guint64 ticks, ProcessTime *processtime)
+{
+ processtime->lowDateTime = ticks & 0xFFFFFFFF;
+ processtime->highDateTime = ticks >> 32;
+}
+
+static void
+wapifiletime_to_processtime (WapiFileTime wapi_filetime, ProcessTime *processtime)
+{
+ processtime->lowDateTime = wapi_filetime.dwLowDateTime;
+ processtime->highDateTime = wapi_filetime.dwHighDateTime;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creation_time, gint64 *exit_time, gint64 *kernel_time, gint64 *user_time)
+{
+ MonoW32HandleProcess *process_handle;
+ ProcessTime *creation_processtime, *exit_processtime, *kernel_processtime, *user_processtime;
+ gboolean res;
+
+ if (!creation_time || !exit_time || !kernel_time || !user_time) {
+ /* Not sure if w32 allows NULLs here or not */
+ return FALSE;
+ }
+
+ creation_processtime = (ProcessTime*) creation_time;
+ exit_processtime = (ProcessTime*) exit_time;
+ kernel_processtime = (ProcessTime*) kernel_time;
+ user_processtime = (ProcessTime*) user_time;
+
+ memset (creation_processtime, 0, sizeof (ProcessTime));
+ memset (exit_processtime, 0, sizeof (ProcessTime));
+ memset (kernel_processtime, 0, sizeof (ProcessTime));
+ memset (user_processtime, 0, sizeof (ProcessTime));
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ gint64 start_ticks, user_ticks, kernel_ticks;
+
+ mono_process_get_times (GINT_TO_POINTER (WAPI_HANDLE_TO_PID (handle)),
+ &start_ticks, &user_ticks, &kernel_ticks);
+
+ ticks_to_processtime (start_ticks, creation_processtime);
+ ticks_to_processtime (user_ticks, kernel_processtime);
+ ticks_to_processtime (kernel_ticks, user_processtime);
+ return TRUE;
+ }
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ wapifiletime_to_processtime (process_handle->create_time, creation_processtime);
+
+ /* A process handle is only signalled if the process has
+ * exited, otherwise exit_processtime isn't set */
+ if (mono_w32handle_issignalled (handle))
+ wapifiletime_to_processtime (process_handle->exit_time, exit_processtime);
+
+#ifdef HAVE_GETRUSAGE
+ if (process_handle->id == getpid ()) {
+ struct rusage time_data;
+ if (getrusage (RUSAGE_SELF, &time_data) == 0) {
+ ticks_to_processtime ((guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10, user_processtime);
+ ticks_to_processtime ((guint64)time_data.ru_stime.tv_sec * 10000000 + (guint64)time_data.ru_stime.tv_usec * 10, kernel_processtime);
+ }
+ }
+#endif
+
+ return TRUE;
+}
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_PROCESS_INTERNALS_H__
+#define __MONO_METADATA_PROCESS_INTERNALS_H__
+
+#include <config.h>
+#include <glib.h>
+
+// On platforms not using classic WIN API support the implementation of bellow methods are hosted in separate source file
+// process-windows-*.c. On platforms using classic WIN API the implementation is still keept in process.c and still declared
+// static and in some places even inlined.
+#if !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+void
+mono_w32process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error);
+
+void
+mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle,
+ HANDLE stderr_handle,STARTUPINFO *startinfo);
+
+gboolean
+mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd,
+ guint32 creation_flags, gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info,
+ PROCESS_INFORMATION *process_info);
+
+MonoBoolean
+mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max);
+
+MonoBoolean
+mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max);
+
+gint32
+mono_icall_get_priority_class (gpointer handle);
+
+MonoBoolean
+mono_icall_set_priority_class (gpointer handle, gint32 priorityClass);
+#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#endif /* __MONO_METADATA_PROCESS_INTERNALS_H__ */
--- /dev/null
+/*
+ * process-windows-uwp.c: UWP process support for Mono.
+ *
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+*/
+#include <config.h>
+#include <glib.h>
+
+#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
+#include <Windows.h>
+#include "mono/metadata/w32process-win32-internals.h"
+
+gboolean
+mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
+{
+ g_unsupported_api ("EnumProcesses");
+ *needed = 0;
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+HANDLE
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
+{
+ HANDLE handle;
+
+ /* GetCurrentProcess returns a pseudo-handle, so use
+ * OpenProcess instead
+ */
+ handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
+ if (handle == NULL)
+ /* FIXME: Throw an exception */
+ return NULL;
+ return handle;
+}
+
+void
+mono_w32process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
+{
+ g_unsupported_api ("GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
+
+ mono_error_init (error);
+ mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+}
+
+MonoObject*
+process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
+{
+ g_unsupported_api ("GetModuleInformation");
+
+ mono_error_init (error);
+ mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetModuleInformation");
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return NULL;
+}
+
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return NULL;
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("ShellExecuteEx");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "ShellExecuteEx");
+ mono_error_set_pending_exception (&mono_error);
+
+ process_info->pid = (guint32)(-ERROR_NOT_SUPPORTED);
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoString *
+ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
+{
+ MonoError error;
+ MonoString *string;
+ gunichar2 name[MAX_PATH];
+ guint32 len;
+
+ len = GetModuleFileName (NULL, name, G_N_ELEMENTS (name));
+ if (len == 0)
+ return NULL;
+
+ string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
+ if (!mono_error_ok (&error))
+ mono_error_set_pending_exception (&error);
+
+ return string;
+}
+
+void
+mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
+{
+ startinfo->cb = sizeof(STARTUPINFO);
+ startinfo->dwFlags = 0;
+ startinfo->hStdInput = INVALID_HANDLE_VALUE;
+ startinfo->hStdOutput = INVALID_HANDLE_VALUE;
+ startinfo->hStdError = INVALID_HANDLE_VALUE;
+ return;
+}
+
+gboolean
+mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd, guint32 creation_flags,
+ gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
+{
+ MonoError mono_error;
+ gchar *api_name = "";
+
+ if (mono_process_info->username) {
+ api_name = "CreateProcessWithLogonW";
+ } else {
+ api_name = "CreateProcess";
+ }
+
+ memset (&process_info, 0, sizeof (PROCESS_INFORMATION));
+ g_unsupported_api (api_name);
+
+ mono_error_init (&mono_error);
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, api_name);
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoBoolean
+mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("GetProcessWorkingSetSize");
+
+ mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "GetProcessWorkingSetSize");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoBoolean
+mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("SetProcessWorkingSetSize");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "SetProcessWorkingSetSize");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+gint32
+mono_icall_get_priority_class (gpointer handle)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("GetPriorityClass");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetPriorityClass");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoBoolean
+mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("SetPriorityClass");
+
+ mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "SetPriorityClass");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
+
+#ifdef _MSC_VER
+// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
+void __mono_win32_process_windows_uwp_quiet_lnk4221(void) {}
+#endif
+#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
--- /dev/null
+/*
+ * process.c: System.Diagnostics.Process support
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * Copyright 2002-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include <winsock2.h>
+#include <windows.h>
+
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/w32process.h>
+#include <mono/metadata/w32process-win32-internals.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/image.h>
+#include <mono/metadata/cil-coff.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/threadpool-ms-io.h>
+#include <mono/utils/strenc.h>
+#include <mono/utils/mono-proclib.h>
+#include <mono/io-layer/io-layer.h>
+/* FIXME: fix this code to not depend so much on the internals */
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/w32handle.h>
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+#include <shellapi.h>
+#endif
+
+void
+mono_w32process_init (void)
+{
+}
+
+void
+mono_w32process_cleanup (void)
+{
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+HANDLE
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
+{
+ HANDLE handle;
+
+ /* GetCurrentProcess returns a pseudo-handle, so use
+ * OpenProcess instead
+ */
+ handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
+ if (handle == NULL)
+ /* FIXME: Throw an exception */
+ return NULL;
+ return handle;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
+
+static gchar*
+mono_process_unquote_application_name (gchar *appname)
+{
+ size_t len = strlen (appname);
+ if (len) {
+ if (appname[len-1] == '\"')
+ appname[len-1] = '\0';
+ if (appname[0] == '\"')
+ appname++;
+ }
+
+ return appname;
+}
+
+static gchar*
+mono_process_quote_path (const gchar *path)
+{
+ gchar *res = g_shell_quote (path);
+ gchar *q = res;
+ while (*q) {
+ if (*q == '\'')
+ *q = '\"';
+ q++;
+ }
+ return res;
+}
+
+/* Only used when UseShellExecute is false */
+static gboolean
+mono_process_complete_path (const gunichar2 *appname, gchar **completed)
+{
+ gchar *utf8app, *utf8appmemory;
+ gchar *found;
+
+ utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
+ utf8app = mono_process_unquote_application_name (utf8appmemory);
+
+ if (g_path_is_absolute (utf8app)) {
+ *completed = mono_process_quote_path (utf8app);
+ g_free (utf8appmemory);
+ return TRUE;
+ }
+
+ if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
+ *completed = mono_process_quote_path (utf8app);
+ g_free (utf8appmemory);
+ return TRUE;
+ }
+
+ found = g_find_program_in_path (utf8app);
+ if (found == NULL) {
+ *completed = NULL;
+ g_free (utf8appmemory);
+ return FALSE;
+ }
+
+ *completed = mono_process_quote_path (found);
+ g_free (found);
+ g_free (utf8appmemory);
+ return TRUE;
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_info)
+{
+ SHELLEXECUTEINFO shellex = {0};
+ gboolean ret;
+
+ shellex.cbSize = sizeof(SHELLEXECUTEINFO);
+ shellex.fMask = (gulong)(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE);
+ shellex.nShow = (gulong)proc_start_info->window_style;
+ shellex.nShow = (gulong)((shellex.nShow == 0) ? 1 : (shellex.nShow == 1 ? 0 : shellex.nShow));
+
+ if (proc_start_info->filename != NULL) {
+ shellex.lpFile = mono_string_chars (proc_start_info->filename);
+ }
+
+ if (proc_start_info->arguments != NULL) {
+ shellex.lpParameters = mono_string_chars (proc_start_info->arguments);
+ }
+
+ if (proc_start_info->verb != NULL &&
+ mono_string_length (proc_start_info->verb) != 0) {
+ shellex.lpVerb = mono_string_chars (proc_start_info->verb);
+ }
+
+ if (proc_start_info->working_directory != NULL &&
+ mono_string_length (proc_start_info->working_directory) != 0) {
+ shellex.lpDirectory = mono_string_chars (proc_start_info->working_directory);
+ }
+
+ if (proc_start_info->error_dialog) {
+ shellex.hwnd = proc_start_info->error_dialog_parent_handle;
+ } else {
+ shellex.fMask = (gulong)(shellex.fMask | SEE_MASK_FLAG_NO_UI);
+ }
+
+ ret = ShellExecuteEx (&shellex);
+ if (ret == FALSE) {
+ process_info->pid = -GetLastError ();
+ } else {
+ process_info->process_handle = shellex.hProcess;
+ process_info->thread_handle = NULL;
+#if !defined(MONO_CROSS_COMPILE)
+ process_info->pid = GetProcessId (shellex.hProcess);
+#else
+ process_info->pid = 0;
+#endif
+ process_info->tid = 0;
+ }
+
+ return ret;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline void
+mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
+{
+ startinfo->cb = sizeof(STARTUPINFO);
+ startinfo->dwFlags = STARTF_USESTDHANDLES;
+ startinfo->hStdInput = stdin_handle;
+ startinfo->hStdOutput = stdout_handle;
+ startinfo->hStdError = stderr_handle;
+ return;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static gboolean
+mono_process_create_process (MonoW32ProcessInfo *mono_process_info, gunichar2 *shell_path,
+ MonoString *cmd, guint32 creation_flags, gchar *env_vars,
+ gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
+{
+ gboolean result = FALSE;
+
+ if (mono_process_info->username) {
+ guint32 logon_flags = mono_process_info->load_user_profile ? LOGON_WITH_PROFILE : 0;
+
+ result = CreateProcessWithLogonW (mono_string_chars (mono_process_info->username),
+ mono_process_info->domain ? mono_string_chars (mono_process_info->domain) : NULL,
+ (const gunichar2 *)mono_process_info->password,
+ logon_flags,
+ shell_path,
+ cmd ? mono_string_chars (cmd) : NULL,
+ creation_flags,
+ env_vars, dir, start_info, process_info);
+
+ } else {
+
+ result = CreateProcess (shell_path,
+ cmd ? mono_string_chars (cmd): NULL,
+ NULL,
+ NULL,
+ TRUE,
+ creation_flags,
+ env_vars,
+ dir,
+ start_info,
+ process_info);
+
+ }
+
+ return result;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+static gboolean
+mono_process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
+{
+ gchar *spath = NULL;
+ gchar *new_cmd, *cmd_utf8;
+ MonoError mono_error;
+
+ *shell_path = NULL;
+ *cmd = proc_start_info->arguments;
+
+ mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
+ if (spath != NULL) {
+ /* Seems like our CreateProcess does not work as the windows one.
+ * This hack is needed to deal with paths containing spaces */
+ if (*cmd) {
+ cmd_utf8 = mono_string_to_utf8_checked (*cmd, &mono_error);
+ if (!mono_error_set_pending_exception (&mono_error)) {
+ new_cmd = g_strdup_printf ("%s %s", spath, cmd_utf8);
+ *cmd = mono_string_new_wrapper (new_cmd);
+ g_free (cmd_utf8);
+ g_free (new_cmd);
+ } else {
+ *cmd = NULL;
+ }
+ }
+ else {
+ *cmd = mono_string_new_wrapper (spath);
+ }
+
+ g_free (spath);
+ }
+
+ return (*cmd != NULL) ? TRUE : FALSE;
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfo *proc_start_info, HANDLE stdin_handle,
+ HANDLE stdout_handle, HANDLE stderr_handle, MonoW32ProcessInfo *process_info)
+{
+ gboolean ret;
+ gunichar2 *dir;
+ STARTUPINFO startinfo={0};
+ PROCESS_INFORMATION procinfo;
+ gunichar2 *shell_path = NULL;
+ gchar *env_vars = NULL;
+ MonoString *cmd = NULL;
+ guint32 creation_flags;
+
+ mono_process_init_startup_info (stdin_handle, stdout_handle, stderr_handle, &startinfo);
+
+ creation_flags = CREATE_UNICODE_ENVIRONMENT;
+ if (proc_start_info->create_no_window)
+ creation_flags |= CREATE_NO_WINDOW;
+
+ if (mono_process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
+ process_info->pid = -ERROR_FILE_NOT_FOUND;
+ return FALSE;
+ }
+
+ if (process_info->env_keys) {
+ gint i, len;
+ MonoString *ms;
+ MonoString *key, *value;
+ gunichar2 *str, *ptr;
+ gunichar2 *equals16;
+
+ for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ ms = mono_array_get (process_info->env_values, MonoString *, i);
+ if (ms == NULL)
+ continue;
+
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ ms = mono_array_get (process_info->env_keys, MonoString *, i);
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ len += 2 * sizeof (gunichar2);
+ }
+
+ equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
+ ptr = str = g_new0 (gunichar2, len + 1);
+ for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ value = mono_array_get (process_info->env_values, MonoString *, i);
+ if (value == NULL)
+ continue;
+
+ key = mono_array_get (process_info->env_keys, MonoString *, i);
+ memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
+ ptr += mono_string_length (key);
+
+ memcpy (ptr, equals16, sizeof (gunichar2));
+ ptr++;
+
+ memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
+ ptr += mono_string_length (value);
+ ptr++;
+ }
+
+ g_free (equals16);
+ env_vars = (gchar *) str;
+ }
+
+ /* The default dir name is "". Turn that into NULL to mean
+ * "current directory"
+ */
+ if (proc_start_info->working_directory == NULL || mono_string_length (proc_start_info->working_directory) == 0)
+ dir = NULL;
+ else
+ dir = mono_string_chars (proc_start_info->working_directory);
+
+ ret = mono_process_create_process (process_info, shell_path, cmd, creation_flags, env_vars, dir, &startinfo, &procinfo);
+
+ g_free (env_vars);
+ if (shell_path != NULL)
+ g_free (shell_path);
+
+ if (ret) {
+ process_info->process_handle = procinfo.hProcess;
+ /*process_info->thread_handle=procinfo.hThread;*/
+ process_info->thread_handle = NULL;
+ if (procinfo.hThread != NULL && procinfo.hThread != INVALID_HANDLE_VALUE)
+ CloseHandle (procinfo.hThread);
+ process_info->pid = procinfo.dwProcessId;
+ process_info->tid = procinfo.dwThreadId;
+ } else {
+ process_info->pid = -GetLastError ();
+ }
+
+ return ret;
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline gboolean
+mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
+{
+ return EnumProcesses (pids, count, needed);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
+{
+ MonoError error;
+ MonoArray *procs;
+ gboolean ret;
+ DWORD needed;
+ int count;
+ DWORD *pids;
+
+ count = 512;
+ do {
+ pids = g_new0 (DWORD, count);
+ ret = mono_process_win_enum_processes (pids, count * sizeof (guint32), &needed);
+ if (ret == FALSE) {
+ MonoException *exc;
+
+ g_free (pids);
+ pids = NULL;
+ exc = mono_get_exception_not_supported ("This system does not support EnumProcesses");
+ mono_set_pending_exception (exc);
+ return NULL;
+ }
+ if (needed < (count * sizeof (guint32)))
+ break;
+ g_free (pids);
+ pids = NULL;
+ count = (count * 3) / 2;
+ } while (TRUE);
+
+ count = needed / sizeof (guint32);
+ procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
+ if (mono_error_set_pending_exception (&error)) {
+ g_free (pids);
+ return NULL;
+ }
+
+ memcpy (mono_array_addr (procs, guint32, 0), pids, needed);
+ g_free (pids);
+ pids = NULL;
+
+ return procs;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
+{
+ return CloseHandle (handle);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
+{
+ return TerminateProcess (handle, exitcode);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
+{
+ return GetExitCodeProcess (handle, exitcode);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline MonoBoolean
+mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
+{
+ return GetProcessWorkingSetSize (handle, min, max);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
+{
+ return mono_icall_get_process_working_set_size (handle, min, max);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline MonoBoolean
+mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
+{
+ return SetProcessWorkingSetSize (handle, min, max);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
+{
+ return mono_icall_set_process_working_set_size (handle, min, max);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline gint32
+mono_icall_get_priority_class (gpointer handle)
+{
+ return GetPriorityClass (handle);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+gint32
+ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
+{
+ return mono_icall_get_priority_class (handle);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline MonoBoolean
+mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
+{
+ return SetPriorityClass (handle, (guint32) priorityClass);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
+{
+ return mono_icall_set_priority_class (handle, priorityClass);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
+{
+ return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
+}
+
+gpointer
+ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
+{
+ return GetCurrentProcess ();
+}
--- /dev/null
+
+#include <glib.h>
+
+#include "w32process.h"
+#include "w32process-internals.h"
+#include "w32process-win32-internals.h"
+#include "object.h"
+#include "object-internals.h"
+#include "class.h"
+#include "class-internals.h"
+#include "image.h"
+#include "utils/mono-proclib.h"
+
+#define LOGDEBUG(...)
+/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) && defined(HOST_WIN32)
+
+static guint32
+mono_w32process_get_pid (gpointer handle)
+{
+ return GetProcessId (handle);
+}
+
+static gboolean
+mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed)
+{
+ return EnumProcessModules (process, (HMODULE *) modules, size, (LPDWORD) needed);
+}
+
+static guint32
+mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ return GetModuleBaseName (process, module, basename, size);
+}
+
+static guint32
+mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ return GetModuleFileNameEx (process, module, basename, size);
+}
+
+static gboolean
+mono_w32process_module_get_information (gpointer process, gpointer module, MODULEINFO *modinfo, guint32 size)
+{
+ return GetModuleInformation (process, module, modinfo, size);
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) && defined(HOST_WIN32) */
+
+static MonoImage *system_image;
+
+static void
+stash_system_image (MonoImage *image)
+{
+ system_image = image;
+}
+
+static MonoClass*
+get_file_version_info_class (void)
+{
+ static MonoClass *file_version_info_class;
+
+ if (file_version_info_class)
+ return file_version_info_class;
+
+ g_assert (system_image);
+
+ return file_version_info_class = mono_class_load_from_name (
+ system_image, "System.Diagnostics", "FileVersionInfo");
+}
+
+static MonoClass*
+get_process_module_class (void)
+{
+ static MonoClass *process_module_class;
+
+ if (process_module_class)
+ return process_module_class;
+
+ g_assert (system_image);
+
+ return process_module_class = mono_class_load_from_name (
+ system_image, "System.Diagnostics", "ProcessModule");
+}
+
+static guint32
+unicode_chars (const gunichar2 *str)
+{
+ guint32 len;
+ for (len = 0; str [len] != '\0'; ++len) {}
+ return len;
+}
+
+static void
+process_set_field_object (MonoObject *obj, const gchar *fieldname, MonoObject *data)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to object at %p", __func__, fieldname, data));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, data);
+}
+
+static void
+process_set_field_string (MonoObject *obj, const gchar *fieldname, const gunichar2 *val, guint32 len, MonoError *error)
+{
+ MonoDomain *domain;
+ MonoClass *klass;
+ MonoClassField *field;
+ MonoString *string;
+
+ mono_error_init (error);
+
+ LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, g_utf16_to_utf8 (val, len, NULL, NULL, NULL)));
+
+ domain = mono_object_domain (obj);
+ g_assert (domain);
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ string = mono_string_new_utf16_checked (domain, val, len, error);
+ return_if_nok (error);
+
+ mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
+}
+
+static void
+process_set_field_string_char (MonoObject *obj, const gchar *fieldname, const gchar *val)
+{
+ MonoDomain *domain;
+ MonoClass *klass;
+ MonoClassField *field;
+ MonoString *string;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, val));
+
+ domain = mono_object_domain (obj);
+ g_assert (domain);
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ string = mono_string_new (domain, val);
+
+ mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
+}
+
+static void
+process_set_field_int (MonoObject *obj, const gchar *fieldname, guint32 val)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to %d", __func__,fieldname, val));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ *(guint32 *)(((char *)obj) + field->offset)=val;
+}
+
+static void
+process_set_field_intptr (MonoObject *obj, const gchar *fieldname, gpointer val)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to %p", __func__, fieldname, val));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ *(gpointer *)(((char *)obj) + field->offset) = val;
+}
+
+static void
+process_set_field_bool (MonoObject *obj, const gchar *fieldname, gboolean val)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to %s", __func__, fieldname, val ? "TRUE":"FALSE"));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ *(guint8 *)(((char *)obj) + field->offset) = val;
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+#define SFI_COMMENTS "\\StringFileInfo\\%02X%02X%02X%02X\\Comments"
+#define SFI_COMPANYNAME "\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName"
+#define SFI_FILEDESCRIPTION "\\StringFileInfo\\%02X%02X%02X%02X\\FileDescription"
+#define SFI_FILEVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\FileVersion"
+#define SFI_INTERNALNAME "\\StringFileInfo\\%02X%02X%02X%02X\\InternalName"
+#define SFI_LEGALCOPYRIGHT "\\StringFileInfo\\%02X%02X%02X%02X\\LegalCopyright"
+#define SFI_LEGALTRADEMARKS "\\StringFileInfo\\%02X%02X%02X%02X\\LegalTrademarks"
+#define SFI_ORIGINALFILENAME "\\StringFileInfo\\%02X%02X%02X%02X\\OriginalFilename"
+#define SFI_PRIVATEBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\PrivateBuild"
+#define SFI_PRODUCTNAME "\\StringFileInfo\\%02X%02X%02X%02X\\ProductName"
+#define SFI_PRODUCTVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\ProductVersion"
+#define SFI_SPECIALBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\SpecialBuild"
+#define EMPTY_STRING (gunichar2*)"\000\000"
+
+typedef struct {
+ const char *name;
+ const char *id;
+} StringTableEntry;
+
+static StringTableEntry stringtable_entries [] = {
+ { "comments", SFI_COMMENTS },
+ { "companyname", SFI_COMPANYNAME },
+ { "filedescription", SFI_FILEDESCRIPTION },
+ { "fileversion", SFI_FILEVERSION },
+ { "internalname", SFI_INTERNALNAME },
+ { "legalcopyright", SFI_LEGALCOPYRIGHT },
+ { "legaltrademarks", SFI_LEGALTRADEMARKS },
+ { "originalfilename", SFI_ORIGINALFILENAME },
+ { "privatebuild", SFI_PRIVATEBUILD },
+ { "productname", SFI_PRODUCTNAME },
+ { "productversion", SFI_PRODUCTVERSION },
+ { "specialbuild", SFI_SPECIALBUILD }
+};
+
+static void
+process_module_string_read (MonoObject *filever, gpointer data, const gchar *fieldname,
+ guchar lang_hi, guchar lang_lo, const gchar *key, MonoError *error)
+{
+ gchar *lang_key_utf8;
+ gunichar2 *lang_key, *buffer;
+ UINT chars;
+
+ mono_error_init (error);
+
+ lang_key_utf8 = g_strdup_printf (key, lang_lo, lang_hi, 0x04, 0xb0);
+
+ LOGDEBUG (g_message ("%s: asking for [%s]", __func__, lang_key_utf8));
+
+ lang_key = g_utf8_to_utf16 (lang_key_utf8, -1, NULL, NULL, NULL);
+
+ if (VerQueryValue (data, lang_key, (gpointer *)&buffer, &chars) && chars > 0) {
+ LOGDEBUG (g_message ("%s: found %d chars of [%s]", __func__, chars, g_utf16_to_utf8 (buffer, chars, NULL, NULL, NULL)));
+ /* chars includes trailing null */
+ process_set_field_string (filever, fieldname, buffer, chars - 1, error);
+ } else {
+ process_set_field_string (filever, fieldname, EMPTY_STRING, 0, error);
+ }
+
+ g_free (lang_key);
+ g_free (lang_key_utf8);
+}
+
+static void
+process_module_stringtable (MonoObject *filever, gpointer data, guchar lang_hi, guchar lang_lo, MonoError *error)
+{
+ for (int i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
+ process_module_string_read (filever, data, stringtable_entries [i].name,
+ lang_hi, lang_lo, stringtable_entries [i].id, error);
+ return_if_nok (error);
+ }
+}
+
+static void
+mono_w32process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
+{
+ DWORD verinfohandle;
+ VS_FIXEDFILEINFO *ffi;
+ gpointer data;
+ DWORD datalen;
+ guchar *trans_data;
+ gunichar2 *query;
+ UINT ffi_size, trans_size;
+ BOOL ok;
+ gunichar2 lang_buf[128];
+ guint32 lang, lang_count;
+
+ mono_error_init (error);
+
+ datalen = GetFileVersionInfoSize (filename, &verinfohandle);
+ if (datalen) {
+ data = g_malloc0 (datalen);
+ ok = GetFileVersionInfo (filename, verinfohandle, datalen, data);
+ if (ok) {
+ query = g_utf8_to_utf16 ("\\", -1, NULL, NULL, NULL);
+ if (query == NULL) {
+ g_free (data);
+ return;
+ }
+
+ if (VerQueryValue (data, query, (gpointer *)&ffi, &ffi_size)) {
+ LOGDEBUG (g_message ("%s: recording assembly: FileName [%s] FileVersionInfo [%d.%d.%d.%d]", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), HIWORD (ffi->dwFileVersionMS), LOWORD (ffi->dwFileVersionMS), HIWORD (ffi->dwFileVersionLS), LOWORD (ffi->dwFileVersionLS)));
+
+ process_set_field_int (filever, "filemajorpart", HIWORD (ffi->dwFileVersionMS));
+ process_set_field_int (filever, "fileminorpart", LOWORD (ffi->dwFileVersionMS));
+ process_set_field_int (filever, "filebuildpart", HIWORD (ffi->dwFileVersionLS));
+ process_set_field_int (filever, "fileprivatepart", LOWORD (ffi->dwFileVersionLS));
+
+ process_set_field_int (filever, "productmajorpart", HIWORD (ffi->dwProductVersionMS));
+ process_set_field_int (filever, "productminorpart", LOWORD (ffi->dwProductVersionMS));
+ process_set_field_int (filever, "productbuildpart", HIWORD (ffi->dwProductVersionLS));
+ process_set_field_int (filever, "productprivatepart", LOWORD (ffi->dwProductVersionLS));
+
+ process_set_field_bool (filever, "isdebug", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_DEBUG) != 0);
+ process_set_field_bool (filever, "isprerelease", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRERELEASE) != 0);
+ process_set_field_bool (filever, "ispatched", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PATCHED) != 0);
+ process_set_field_bool (filever, "isprivatebuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRIVATEBUILD) != 0);
+ process_set_field_bool (filever, "isspecialbuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_SPECIALBUILD) != 0);
+ }
+ g_free (query);
+
+ query = g_utf8_to_utf16 ("\\VarFileInfo\\Translation", -1, NULL, NULL, NULL);
+ if (query == NULL) {
+ g_free (data);
+ return;
+ }
+
+ if (VerQueryValue (data, query, (gpointer *)&trans_data, &trans_size)) {
+ /* use the first language ID we see */
+ if (trans_size >= 4) {
+ LOGDEBUG (g_message("%s: %s has 0x%0x 0x%0x 0x%0x 0x%0x", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), trans_data[0], trans_data[1], trans_data[2], trans_data[3]));
+ lang = (trans_data[0]) | (trans_data[1] << 8) | (trans_data[2] << 16) | (trans_data[3] << 24);
+ /* Only give the lower 16 bits to VerLanguageName, as Windows gets confused otherwise */
+ lang_count = VerLanguageName (lang & 0xFFFF, lang_buf, 128);
+ if (lang_count) {
+ process_set_field_string (filever, "language", lang_buf, lang_count, error);
+ return_if_nok (error);
+ }
+ process_module_stringtable (filever, data, trans_data[0], trans_data[1], error);
+ return_if_nok (error);
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
+ /* No strings, so set every field to the empty string */
+ process_set_field_string (filever, stringtable_entries [i].name, EMPTY_STRING, 0, error);
+ return_if_nok (error);
+ }
+
+ /* And language seems to be set to en_US according to bug 374600 */
+ lang_count = VerLanguageName (0x0409, lang_buf, 128);
+ if (lang_count) {
+ process_set_field_string (filever, "language", lang_buf, lang_count, error);
+ return_if_nok (error);
+ }
+ }
+
+ g_free (query);
+ }
+ g_free (data);
+ }
+}
+
+#endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+void
+ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename)
+{
+ MonoError error;
+
+ stash_system_image (mono_object_class (this_obj)->image);
+
+ mono_w32process_get_fileversion (this_obj, mono_string_chars (filename), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return;
+ }
+
+ process_set_field_string (this_obj, "filename", mono_string_chars (filename), mono_string_length (filename), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ }
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+static GPtrArray*
+get_domain_assemblies (MonoDomain *domain)
+{
+ GSList *tmp;
+ GPtrArray *assemblies;
+
+ /*
+ * Make a copy of the list of assemblies because we can't hold the assemblies
+ * lock while creating objects etc.
+ */
+ assemblies = g_ptr_array_new ();
+ mono_domain_assemblies_lock (domain);
+ for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
+ MonoAssembly *ass = (MonoAssembly *)tmp->data;
+ if (ass->image->fileio_used)
+ continue;
+ g_ptr_array_add (assemblies, ass);
+ }
+ mono_domain_assemblies_unlock (domain);
+
+ return assemblies;
+}
+
+static MonoObject*
+process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
+{
+ MonoObject *item, *filever;
+ MonoDomain *domain = mono_domain_get ();
+ MODULEINFO modinfo;
+ BOOL ok;
+
+ mono_error_init (error);
+
+ /* Build a System.Diagnostics.ProcessModule with the data. */
+ item = mono_object_new_checked (domain, proc_class, error);
+ return_val_if_nok (error, NULL);
+
+ filever = mono_object_new_checked (domain, get_file_version_info_class (), error);
+ return_val_if_nok (error, NULL);
+
+ mono_w32process_get_fileversion (filever, filename, error);
+ return_val_if_nok (error, NULL);
+
+ process_set_field_string (filever, "filename", filename, unicode_chars (filename), error);
+ return_val_if_nok (error, NULL);
+
+ ok = mono_w32process_module_get_information (process, mod, &modinfo, sizeof(MODULEINFO));
+ if (ok) {
+ process_set_field_intptr (item, "baseaddr", modinfo.lpBaseOfDll);
+ process_set_field_intptr (item, "entryaddr", modinfo.EntryPoint);
+ process_set_field_int (item, "memory_size", modinfo.SizeOfImage);
+ }
+
+ process_set_field_string (item, "filename", filename, unicode_chars (filename), error);
+ return_val_if_nok (error, NULL);
+
+ process_set_field_string (item, "modulename", modulename, unicode_chars (modulename), error);
+ return_val_if_nok (error, NULL);
+
+ process_set_field_object (item, "version_info", filever);
+
+ return item;
+}
+
+static void
+process_get_assembly_fileversion (MonoObject *filever, MonoAssembly *assembly)
+{
+ process_set_field_int (filever, "filemajorpart", assembly->aname.major);
+ process_set_field_int (filever, "fileminorpart", assembly->aname.minor);
+ process_set_field_int (filever, "filebuildpart", assembly->aname.build);
+}
+
+static MonoObject*
+process_get_module (MonoAssembly *assembly, MonoClass *proc_class, MonoError *error)
+{
+ MonoObject *item, *filever;
+ MonoDomain *domain;
+ gchar *filename;
+ const gchar *modulename;
+
+ mono_error_init (error);
+
+ domain = mono_domain_get ();
+
+ modulename = assembly->aname.name;
+
+ /* Build a System.Diagnostics.ProcessModule with the data. */
+ item = mono_object_new_checked (domain, proc_class, error);
+ return_val_if_nok (error, NULL);
+
+ filever = mono_object_new_checked (domain, get_file_version_info_class (), error);
+ return_val_if_nok (error, NULL);
+
+ filename = g_strdup_printf ("[In Memory] %s", modulename);
+
+ process_get_assembly_fileversion (filever, assembly);
+ process_set_field_string_char (filever, "filename", filename);
+ process_set_field_object (item, "version_info", filever);
+
+ process_set_field_intptr (item, "baseaddr", assembly->image->raw_data);
+ process_set_field_int (item, "memory_size", assembly->image->raw_data_len);
+ process_set_field_string_char (item, "filename", filename);
+ process_set_field_string_char (item, "modulename", modulename);
+
+ g_free (filename);
+
+ return item;
+}
+
+/* Returns an array of System.Diagnostics.ProcessModule */
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
+{
+ MonoError error;
+ MonoArray *temp_arr = NULL;
+ MonoArray *arr;
+ HMODULE mods[1024];
+ gunichar2 filename[MAX_PATH];
+ gunichar2 modname[MAX_PATH];
+ DWORD needed;
+ guint32 count = 0, module_count = 0, assembly_count = 0;
+ guint32 i, num_added = 0;
+ GPtrArray *assemblies = NULL;
+
+ stash_system_image (mono_object_class (this_obj)->image);
+
+ if (mono_w32process_get_pid (process) == mono_process_current_pid ()) {
+ assemblies = get_domain_assemblies (mono_domain_get ());
+ assembly_count = assemblies->len;
+ }
+
+ if (mono_w32process_try_get_modules (process, mods, sizeof(mods), &needed))
+ module_count += needed / sizeof(HMODULE);
+
+ count = module_count + assembly_count;
+ temp_arr = mono_array_new_checked (mono_domain_get (), get_process_module_class (), count, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+
+ for (i = 0; i < module_count; i++) {
+ if (mono_w32process_module_get_name (process, mods[i], modname, MAX_PATH)
+ && mono_w32process_module_get_filename (process, mods[i], filename, MAX_PATH))
+ {
+ MonoObject *module = process_add_module (process, mods[i], filename, modname, get_process_module_class (), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ mono_array_setref (temp_arr, num_added++, module);
+ }
+ }
+
+ if (assemblies) {
+ for (i = 0; i < assembly_count; i++) {
+ MonoAssembly *ass = (MonoAssembly *)g_ptr_array_index (assemblies, i);
+ MonoObject *module = process_get_module (ass, get_process_module_class (), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ mono_array_setref (temp_arr, num_added++, module);
+ }
+ g_ptr_array_free (assemblies, TRUE);
+ }
+
+ if (count == num_added) {
+ arr = temp_arr;
+ } else {
+ /* shorter version of the array */
+ arr = mono_array_new_checked (mono_domain_get (), get_process_module_class (), num_added, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+
+ for (i = 0; i < num_added; i++)
+ mono_array_setref (arr, i, mono_array_get (temp_arr, MonoObject*, i));
+ }
+
+ return arr;
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+MonoString *
+ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
+{
+ MonoError error;
+ MonoString *string;
+ gunichar2 name[MAX_PATH];
+ guint32 len;
+ gboolean ok;
+ HMODULE mod;
+ DWORD needed;
+
+ ok = mono_w32process_try_get_modules (process, &mod, sizeof(mod), &needed);
+ if (!ok)
+ return NULL;
+
+ len = mono_w32process_module_get_name (process, mod, name, MAX_PATH);
+ if (len == 0)
+ return NULL;
+
+ string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
+ if (!mono_error_ok (&error))
+ mono_error_set_pending_exception (&error);
+
+ return string;
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+gint64
+ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error)
+{
+ MonoProcessError perror;
+ guint64 res;
+
+ res = mono_process_get_data_with_error (GINT_TO_POINTER (pid), (MonoProcessData)data_type, &perror);
+ if (error)
+ *error = perror;
+ return res;
+}
--- /dev/null
+/*
+ * w32process.h: System.Diagnostics.Process support
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * (C) 2002 Ximian, Inc.
+ */
+
+#ifndef _MONO_METADATA_W32PROCESS_H_
+#define _MONO_METADATA_W32PROCESS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <mono/metadata/object.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ MONO_W32PROCESS_PRIORITY_CLASS_NORMAL = 0x0020,
+ MONO_W32PROCESS_PRIORITY_CLASS_IDLE = 0x0040,
+ MONO_W32PROCESS_PRIORITY_CLASS_HIGH = 0x0080,
+ MONO_W32PROCESS_PRIORITY_CLASS_REALTIME = 0x0100,
+ MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL = 0x4000,
+ MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL = 0x8000,
+} MonoW32ProcessPriorityClass;
+
+typedef struct
+{
+ gpointer process_handle;
+ gpointer thread_handle;
+ guint32 pid; /* Contains GetLastError () on failure */
+ guint32 tid;
+ MonoArray *env_keys;
+ MonoArray *env_values;
+ MonoString *username;
+ MonoString *domain;
+ gpointer password; /* BSTR from SecureString in 2.0 profile */
+ MonoBoolean load_user_profile;
+} MonoW32ProcessInfo;
+
+typedef struct
+{
+ MonoObject object;
+ MonoString *filename;
+ MonoString *arguments;
+ MonoString *working_directory;
+ MonoString *verb;
+ guint32 window_style;
+ MonoBoolean error_dialog;
+ gpointer error_dialog_parent_handle;
+ MonoBoolean use_shell_execute;
+ MonoString *username;
+ MonoString *domain;
+ MonoObject *password; /* SecureString in 2.0 profile, dummy in 1.x */
+ MonoString *password_in_clear_text;
+ MonoBoolean load_user_profile;
+ MonoBoolean redirect_standard_input;
+ MonoBoolean redirect_standard_output;
+ MonoBoolean redirect_standard_error;
+ MonoObject *encoding_stdout;
+ MonoObject *encoding_stderr;
+ MonoBoolean create_no_window;
+ MonoObject *weak_parent_process;
+ MonoObject *envVars;
+} MonoW32ProcessStartInfo;
+
+void
+mono_w32process_init (void);
+
+void
+mono_w32process_cleanup (void);
+
+#ifndef HOST_WIN32
+
+void
+mono_w32process_set_cli_launcher (gchar *path);
+
+gchar*
+mono_w32process_get_path (pid_t pid);
+
+#endif
+
+gpointer
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid);
+
+MonoArray*
+ves_icall_System_Diagnostics_Process_GetProcesses_internal (void);
+
+MonoArray*
+ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, gpointer process);
+
+void
+ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename);
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_handle);
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfo *proc_start_info, gpointer stdin_handle,
+ gpointer stdout_handle, gpointer stderr_handle, MonoW32ProcessInfo *process_handle);
+
+MonoString*
+ves_icall_System_Diagnostics_Process_ProcessName_internal (gpointer process);
+
+gint64
+ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error);
+
+gpointer
+ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max);
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max);
+
+gint32
+ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle);
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime);
+
+G_END_DECLS
+
+#endif /* _MONO_METADATA_W32PROCESS_H_ */
+
#include "w32handle-namespace.h"
#include "mono/io-layer/io-layer.h"
#include "mono/utils/mono-logger-internals.h"
-#include "mono/utils/w32handle.h"
+#include "mono/metadata/w32handle.h"
typedef struct {
guint32 val;
#elif defined(TARGET_POWERPC)
{
guint8 buf [32];
- guint8 *code;
emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
code = buf;
for (i = 0; i < klass->field.count; ++i) {
if (field == &klass->fields [i])
- return MONO_TOKEN_FIELD_DEF | (klass->field.first + 1 + i);
+ return MONO_TOKEN_FIELD_DEF | (mono_class_get_first_field_idx (klass) + 1 + i);
}
g_assert_not_reached ();
* information.
*/
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
guint32 token;
g_assert (klass->type_token);
encode_value (MONO_AOT_TYPEREF_TYPESPEC_TOKEN, p, &p);
encode_value (token, p, &p);
} else {
- MonoClass *gclass = klass->generic_class->container_class;
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ MonoClass *gclass = mono_class_get_generic_class (klass)->container_class;
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
static int count = 0;
guint8 *p1 = p;
/*
* The encoding of generic instances is large so emit them only once.
*/
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
guint32 token;
g_assert (klass->type_token);
MonoMarshalType *info;
int i;
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if (mono_class_is_auto_layout (klass))
return FALSE;
info = mono_marshal_load_type_info (klass);
memset (ctx, 0, sizeof (MonoGenericContext));
- if (method->klass->generic_container) {
- shared_context = method->klass->generic_container->context;
+ if (mono_class_is_gtd (method->klass)) {
+ shared_context = mono_class_get_generic_container (method->klass)->context;
inst = shared_context.class_inst;
args = g_new0 (MonoType*, inst->type_argc);
if (!klass->delegate || klass == mono_defaults.delegate_class || klass == mono_defaults.multicastdelegate_class)
continue;
- if (!klass->generic_container) {
+ if (!mono_class_is_gtd (klass)) {
method = mono_get_delegate_invoke (klass);
m = mono_marshal_get_delegate_invoke (method, NULL);
add_method (acfg, del_invoke);
}
}
- } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->generic_container) {
+ } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (klass)) {
MonoError error;
MonoGenericContext ctx;
MonoMethod *inst, *gshared;
if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
if (method->is_generic) {
// FIXME:
- } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && method->klass->generic_container) {
+ } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (method->klass)) {
MonoError error;
MonoGenericContext ctx;
MonoMethod *inst, *gshared, *m;
continue;
}
- if (klass->valuetype && !klass->generic_container && can_marshal_struct (klass) &&
+ if (klass->valuetype && !mono_class_is_gtd (klass) && can_marshal_struct (klass) &&
!(klass->nested_in && strstr (klass->nested_in->name, "<PrivateImplementationDetails>") == klass->nested_in->name)) {
add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
return TRUE;
if (klass->rank)
return has_type_vars (klass->element_class);
- if (klass->generic_class) {
- MonoGenericContext *context = &klass->generic_class->context;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericContext *context = &mono_class_get_generic_class (klass)->context;
if (context->class_inst) {
int i;
return TRUE;
}
}
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
return TRUE;
return FALSE;
}
mono_class_init (klass);
- if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
+ if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open)
return;
if (has_type_vars (klass))
return;
- if (!klass->generic_class && !klass->rank)
+ if (!mono_class_is_ginst (klass) && !klass->rank)
return;
if (mono_class_has_failure (klass))
* Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
* Enable this only for some classes since gsharedvt might not support all methods.
*/
- if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+ if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst) &&
(!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
use_gsharedvt = TRUE;
*/
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") &&
(!strcmp(klass->name, "ICollection`1") || !strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IList`1") || !strcmp (klass->name, "IEnumerator`1") || !strcmp (klass->name, "IReadOnlyList`1"))) {
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *array_class = mono_bounded_array_class_get (tclass, 1, FALSE);
gpointer iter;
char *name_prefix;
break;
}
g_assert (nclass);
- nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (klass->generic_class), &error);
+ nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (mono_class_get_generic_class (klass)), &error);
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
add_generic_class (acfg, nclass, FALSE, "ICollection<T>");
}
/* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
MonoError error;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *icomparable, *gcomparer, *icomparable_inst;
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of GenericEqualityComparer<T> which is created dynamically by EqualityComparer<T> */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
MonoError error;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *iface, *gcomparer, *iface_inst;
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of EnumComparer<T> which is created dynamically by EqualityComparer<T> for enums */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
MonoClass *enum_comparer;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of ObjectComparer<T> which is created dynamically by Comparer<T> for enums */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
MonoClass *comparer;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoGenericContext ctx;
MonoType *args [16];
g_free (type_argv);
}
- if (method->is_generic || method->klass->generic_container)
+ if (method->is_generic || mono_class_is_gtd (method->klass))
declaring_method = method;
else
declaring_method = mono_method_get_declaring_generic_method (method);
if (callee_cfg) {
gboolean direct_callable = TRUE;
- if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+ if (direct_callable && !(!callee_cfg->has_got_slots && mono_class_is_before_field_init (callee_cfg->method->klass)))
direct_callable = FALSE;
if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
// FIXME: Maybe call the wrapper directly ?
encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);
break;
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
+ case MONO_PATCH_INFO_GET_TLS_TRAMP:
break;
default:
g_warning ("unable to handle jump info %d", patch_info->type);
mono_class_has_finalizer (klass);
- if (klass->generic_container || cant_encode) {
+ if (mono_class_is_gtd (klass) || cant_encode) {
encode_value (-1, p, &p);
} else {
encode_value (klass->vtable_size, p, &p);
- encode_value ((klass->generic_container ? (1 << 8) : 0) | (no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | ((klass->ext && klass->ext->nested_classes) ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
+ encode_value ((mono_class_is_gtd (klass) ? (1 << 8) : 0) | (no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | ((klass->ext && klass->ext->nested_classes) ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
if (klass->has_cctor)
encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
if (klass->has_finalize)
if (!MONO_TYPE_ISSTRUCT (t))
return TRUE;
klass = mono_class_from_mono_type (t);
- orig_ctx = &klass->generic_class->context;
+ orig_ctx = &mono_class_get_generic_class (klass)->context;
inst = orig_ctx->class_inst;
if (inst) {
InterlockedIncrement (&acfg->stats.mcount);
#if 0
- if (method->is_generic || method->klass->generic_container) {
+ if (method->is_generic || mono_class_is_gtd (method->klass)) {
InterlockedIncrement (&acfg->stats.genericcount);
return;
}
case MONO_PATCH_INFO_VTABLE: {
MonoClass *klass = patch_info->data.klass;
- if (klass->generic_class && !mini_class_is_generic_sharable (klass))
+ if (mono_class_is_ginst (klass) && !mini_class_is_generic_sharable (klass))
add_generic_class_with_depth (acfg, klass, depth + 5, "vtable");
break;
}
MonoClass *klass = patch_info->data.field->parent;
/* The .cctor needs to run at runtime. */
- if (klass->generic_class && !mono_generic_context_is_sharable_full (&klass->generic_class->context, FALSE, FALSE) && mono_class_get_cctor (klass))
+ if (mono_class_is_ginst (klass) && !mono_generic_context_is_sharable_full (&mono_class_get_generic_class (klass)->context, FALSE, FALSE) && mono_class_get_cctor (klass))
add_extra_method_with_depth (acfg, mono_class_get_cctor (klass), depth + 1);
break;
}
static int
execute_system (const char * command)
{
- int status;
+ int status = 0;
#if _WIN32
// We need an extra set of quotes around the whole command to properly handle commands
sig = mono_method_signature (method);
- if (method->klass->generic_class)
- class_ginst = method->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (method->klass))
+ class_ginst = mono_class_get_generic_class (method->klass)->context.class_inst;
if (method->is_inflated)
ginst = ((MonoMethodInflated*)method)->context.method_inst;
if (!method->wrapper_type) {
char *full_name;
- if (klass->generic_class)
- full_name = mono_type_full_name (&klass->generic_class->container_class->byval_arg);
+ if (mono_class_is_ginst (klass))
+ full_name = mono_type_full_name (&mono_class_get_generic_class (klass)->container_class->byval_arg);
else
full_name = mono_type_full_name (&klass->byval_arg);
}
*/
- if (method->is_generic || method->klass->generic_container)
+ if (method->is_generic || mono_class_is_gtd (method->klass))
/* Compile the ref shared version instead */
method = mini_get_shared_method (method);
method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
- if (method->is_generic || method->klass->generic_container) {
+ if (method->is_generic || mono_class_is_gtd (method->klass)) {
MonoMethod *gshared;
gshared = mini_get_shared_method_full (method, TRUE, TRUE);
GPtrArray *frag;
int len, j;
GPtrArray *threads;
- HANDLE handle;
+ MonoThreadHandle *thread_handle;
gpointer *user_data;
MonoMethod **methods;
user_data [1] = acfg;
user_data [2] = frag;
- handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, NULL, NULL);
- g_ptr_array_add (threads, handle);
+ thread_handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, NULL, NULL);
+ g_ptr_array_add (threads, thread_handle);
}
g_free (methods);
for (i = 0; i < threads->len; ++i) {
- WaitForSingleObjectEx (g_ptr_array_index (threads, i), INFINITE, FALSE);
+ mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), INFINITE, FALSE);
mono_threads_close_thread_handle (g_ptr_array_index (threads, i));
}
} else {
get_got_offset (acfg, FALSE, ji);
get_got_offset (acfg, TRUE, ji);
+ ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_GET_TLS_TRAMP;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
for (i = 0; i < sizeof (preinited_jit_icalls) / sizeof (char*); ++i) {
ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
else
acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
- acfg->fp = fopen (acfg->tmpfname, "w+");
+ acfg->fp = fopen (acfg->tmpfname, "w+");
} else {
int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
acfg->fp = fdopen (i, "w+");
gclass = decode_klass_ref (module, p, &p, error);
if (!gclass)
return NULL;
- g_assert (gclass->generic_container);
+ g_assert (mono_class_is_gtd (gclass));
memset (&ctx, 0, sizeof (ctx));
ctx.class_inst = decode_generic_inst (module, p, &p, error);
if (!class_def)
return NULL;
- container = class_def->generic_container;
+ container = mono_class_try_get_generic_container (class_def); //FIXME is this a case for a try_get?
}
} else {
// We didn't decode is_method, so we have to infer it from type enum.
gclass = decode_klass_ref (module, p, &p, error);
if (!gclass)
goto fail;
- g_assert (gclass->generic_container);
+ g_assert (mono_class_is_gtd (gclass));
memset (&ctx, 0, sizeof (ctx));
ctx.class_inst = decode_generic_inst (module, p, &p, error);
if (!type)
goto fail;
klass = mono_class_from_mono_type (type);
- t->data.generic_class = klass->generic_class;
+ t->data.generic_class = mono_class_get_generic_class (klass);
break;
}
case MONO_TYPE_ARRAY: {
memset (&ctx, 0, sizeof (ctx));
- if (FALSE && klass->generic_class) {
- ctx.class_inst = klass->generic_class->context.class_inst;
+ if (FALSE && mono_class_is_ginst (klass)) {
+ ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
ctx.method_inst = NULL;
ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, error);
guint8 *p;
gboolean err;
- if (klass->rank || !amodule)
+ if (klass->rank || !klass->type_token || !amodule)
return FALSE;
p = (guint8*)&amodule->blob [mono_aot_get_offset (amodule->class_info_offsets, mono_metadata_token_index (klass->type_token) - 1)];
break;
}
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
+ case MONO_PATCH_INFO_GET_TLS_TRAMP:
break;
case MONO_PATCH_INFO_AOT_JIT_INFO:
ji->data.index = decode_value (p, &p);
gboolean inited_ok = TRUE;
if (init_class)
inited_ok = mono_runtime_class_init_full (mono_class_vtable (domain, init_class), error);
- else if (from_plt && klass_to_run_ctor && !klass_to_run_ctor->generic_container)
+ else if (from_plt && klass_to_run_ctor && !mono_class_is_gtd (klass_to_run_ctor))
inited_ok = mono_runtime_class_init_full (mono_class_vtable (domain, klass_to_run_ctor), error);
if (!inited_ok)
return FALSE;
MonoGenericContext context = { NULL, NULL };
MonoClass *klass = rgctx->class_vtable->klass;
- if (klass->generic_class)
- context.class_inst = klass->generic_class->context.class_inst;
- else if (klass->generic_container)
- context.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (klass))
+ context.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
+ else if (mono_class_is_gtd (klass))
+ context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
context.method_inst = rgctx->method_inst;
init_llvmonly_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context);
* Copyright 2011 Xamarin Inc. http://www.xamarin.com
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
- #include "mini.h"
+#include "config.h"
#ifndef DISABLE_JIT
-
+
+#include "mini.h"
/*
* Returns true if @bb is a basic block which falls through the next block.
static MonoNativeThreadId debugger_thread_id;
-static HANDLE debugger_thread_handle;
+static MonoThreadHandle *debugger_thread_handle;
static int log_level;
if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this_arg) {
if (!strcmp (m->name, ".ctor")) {
- if (m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT)
+ if (mono_class_is_abstract (m->klass))
return ERR_INVALID_ARGUMENT;
else {
MonoError error;
buffer_add_id (buf, 0);
buffer_add_int (buf, klass->type_token);
buffer_add_byte (buf, klass->rank);
- buffer_add_int (buf, klass->flags);
+ buffer_add_int (buf, mono_class_get_flags (klass));
b = 0;
type = &klass->byval_arg;
// FIXME: Can't decide whenever a class represents a byref type
b |= (1 << 3);
if (klass->enumtype)
b |= (1 << 4);
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
b |= (1 << 5);
- if (klass->generic_container || klass->generic_class)
+ if (mono_class_is_gtd (klass) || mono_class_is_ginst (klass))
b |= (1 << 6);
buffer_add_byte (buf, b);
nnested = 0;
while ((nested = mono_class_get_nested_types (klass, &iter)))
buffer_add_typeid (buf, domain, nested);
if (CHECK_PROTOCOL_VERSION (2, 12)) {
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
buffer_add_typeid (buf, domain, klass);
- else if (klass->generic_class)
- buffer_add_typeid (buf, domain, klass->generic_class->container_class);
+ else if (mono_class_is_ginst (klass))
+ buffer_add_typeid (buf, domain, mono_class_get_generic_class (klass)->container_class);
else
buffer_add_id (buf, 0);
}
if (CHECK_PROTOCOL_VERSION (2, 15)) {
int count, i;
- if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
count = inst->type_argc;
buffer_add_int (buf, count);
for (i = 0; i < count; i++)
buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv [i]));
- } else if (klass->generic_container) {
- MonoGenericContainer *container = klass->generic_container;
+ } else if (mono_class_is_gtd (klass)) {
+ MonoGenericContainer *container = mono_class_get_generic_container (klass);
MonoClass *pklass;
count = container->type_argc;
}
ginst = mono_metadata_get_generic_inst (type_argc, type_argv);
g_free (type_argv);
- tmp_context.class_inst = method->klass->generic_class ? method->klass->generic_class->context.class_inst : NULL;
+ tmp_context.class_inst = mono_class_is_ginst (method->klass) ? mono_class_get_generic_class (method->klass)->context.class_inst : NULL;
tmp_context.method_inst = ginst;
inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/coree.h>
#include <mono/metadata/attach.h>
+#include <mono/metadata/w32process.h>
#include "mono/utils/mono-counters.h"
#include "mono/utils/mono-hwcap.h"
#include "mono/utils/mono-logger-internals.h"
-#include "mono/utils/w32handle.h"
+#include "mono/metadata/w32handle.h"
#include "mini.h"
#include "jit.h"
(method->flags & METHOD_ATTRIBUTE_ABSTRACT))
continue;
- if (method->klass->generic_container)
+ if (mono_class_is_gtd (method->klass))
continue;
sig = mono_method_signature (method);
if (!sig) {
{
char *runtime_path;
- runtime_path = wapi_process_get_path (getpid ());
+ runtime_path = mono_w32process_get_path (getpid ());
if (runtime_path) {
- wapi_process_set_cli_launcher (runtime_path);
+ mono_w32process_set_cli_launcher (runtime_path);
g_free (runtime_path);
}
}
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
int i, ctx_reg, size;
+ guint8 *labels [16];
size = 256;
code = start = mono_global_codeman_reserve (size);
arm_movx (code, ARMREG_IP0, ARMREG_R0);
ctx_reg = ARMREG_IP0;
+
/* Restore fregs */
+ arm_ldrx (code, ARMREG_IP1, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, has_fregs));
+ labels [0] = code;
+ arm_cbzx (code, ARMREG_IP1, 0);
for (i = 0; i < 32; ++i)
arm_ldrfpx (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8));
+ mono_arm_patch (labels [0], code, MONO_R_ARM64_CBZ);
/* Restore gregs */
// FIXME: Restore less registers
// FIXME: fp should be restored later
{
guint8 *code;
guint8* start;
- int size, offset, gregs_offset, fregs_offset, ctx_offset, num_fregs, frame_size;
+ int i, size, offset, gregs_offset, fregs_offset, ctx_offset, num_fregs, frame_size;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
+ guint8 *labels [16];
size = 512;
start = code = mono_global_codeman_reserve (size);
arm_strx (code, ARMREG_R0, ARMREG_FP, ctx_offset);
/* Save gregs */
code = mono_arm_emit_store_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS | (1 << ARMREG_FP), ARMREG_FP, gregs_offset);
- /* No need to save/restore fregs, since we don't currently use them */
+ /* Save fregs */
+ for (i = 0; i < num_fregs; ++i)
+ arm_strfpx (code, ARMREG_D8 + i, ARMREG_FP, fregs_offset + (i * 8));
/* Load regs from ctx */
code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs));
+ /* Load fregs */
+ arm_ldrx (code, ARMREG_IP0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, has_fregs));
+ labels [0] = code;
+ arm_cbzx (code, ARMREG_IP0, 0);
+ for (i = 0; i < num_fregs; ++i)
+ arm_ldrfpx (code, ARMREG_D8 + i, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8));
+ mono_arm_patch (labels [0], code, MONO_R_ARM64_CBZ);
/* Load fp */
arm_ldrx (code, ARMREG_FP, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_FP * 8));
/* Restore regs */
code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_FP, gregs_offset);
+ /* Restore fregs */
+ for (i = 0; i < num_fregs; ++i)
+ arm_ldrfpx (code, ARMREG_D8 + i, ARMREG_FP, fregs_offset + (i * 8));
/* Destroy frame */
code = mono_arm_emit_destroy_frame (code, frame_size, (1 << ARMREG_IP0));
arm_retx (code, ARMREG_LR);
memset (&ctx, 0, sizeof (MonoContext));
memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32);
memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8);
+ ctx.has_fregs = 1;
ctx.pc = pc;
if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
memset (&ctx, 0, sizeof (MonoContext));
memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32);
memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8);
+ ctx.has_fregs = 1;
ctx.pc = pc;
mono_resume_unwind (&ctx);
if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
MonoGenericContext context = { NULL, NULL };
- if (res->klass->generic_class)
- context.class_inst = res->klass->generic_class->context.class_inst;
- else if (res->klass->generic_container)
- context.class_inst = res->klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (res->klass))
+ context.class_inst = mono_class_get_generic_class (res->klass)->context.class_inst;
+ else if (mono_class_is_gtd (res->klass))
+ context.class_inst = mono_class_get_generic_container (res->klass)->context.class_inst;
context.method_inst = mono_method_get_context (method)->method_inst;
res = mono_class_inflate_generic_method_checked (res, &context, &error);
return NULL;
}
vmethod = mono_object_get_virtual_method (obj, method);
- g_assert (!vmethod->klass->generic_container);
- g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
+ g_assert (!mono_class_is_gtd (vmethod->klass));
+ g_assert (!mono_class_is_ginst (vmethod->klass) || !mono_class_get_generic_class (vmethod->klass)->context.class_inst->is_open);
g_assert (!context->method_inst || !context->method_inst->is_open);
addr = mono_compile_method_checked (vmethod, &error);
mono_error_init (error);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
MonoObject *this_obj;
/* Have to use the receiver's type instead of klass, the receiver is a ref type */
mono_class_setup_vtable (klass);
g_assert (klass->vtable);
vt_slot = mono_method_get_vtable_slot (cmethod);
- if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (cmethod->klass)) {
iface_offset = mono_class_interface_offset (klass, cmethod->klass);
g_assert (iface_offset != -1);
vt_slot += iface_offset;
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
generic_virtual = imt_method;
g_assert (generic_virtual);
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
g_assert (generic_virtual->is_inflated);
context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
bundle_save_library_initialized = 1;
char *path = g_build_filename (g_get_tmp_dir (), "mono-bundle-XXXXXX", NULL);
bundled_dylibrary_directory = g_mkdtemp (path);
- g_free (path);
+ /* don't free path - mkdtemp modifies it in place, and bundled_dylibrary_directory is an alias of it */
if (bundled_dylibrary_directory == NULL)
return;
atexit (delete_bundled_libraries);
mono_register_bundled_assemblies ((const MonoBundledAssembly **) assemblies->data);
new_argv = g_new (char *, (*ref_argc)+1);
- for (j = 0; j < *ref_argc; j++)
- new_argv [j] = (*ref_argv)[j];
- new_argv [j] = entry_point;
+ new_argv [0] = (*ref_argv)[0];
+ new_argv [1] = entry_point;
+ for (j = 1; j < *ref_argc; j++)
+ new_argv [j+1] = (*ref_argv)[j];
*ref_argv = new_argv;
(*ref_argc)++;
{
int max_iid_reg = alloc_preg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, max_iid_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id));
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU4_MEMBASE, max_iid_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id));
mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target);
}
{
int max_iid_reg = alloc_preg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, max_iid_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, max_interface_id));
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU4_MEMBASE, max_iid_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, max_interface_id));
mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target);
}
mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class);
} else if (klass->cast_class == mono_defaults.enum_class) {
mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class);
- } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ } else if (mono_class_is_interface (klass->cast_class)) {
mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, NULL, NULL);
} else {
// Pass -1 as obj_reg to skip the check below for arrays of arrays
gboolean pass_mrgctx = FALSE;
if (((cmethod->flags & METHOD_ATTRIBUTE_STATIC) || cmethod->klass->valuetype) &&
- (cmethod->klass->generic_class || cmethod->klass->generic_container)) {
+ (mono_class_is_ginst (cmethod->klass) || mono_class_is_gtd (cmethod->klass))) {
gboolean sharable = FALSE;
if (mono_method_is_generic_sharable_full (cmethod, TRUE, TRUE, TRUE))
if (!sig)
sig = mono_method_signature (method);
- if (cfg->llvm_only && (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
+ if (cfg->llvm_only && (mono_class_is_interface (method->klass)))
g_assert_not_reached ();
if (rgctx_arg) {
if (cfg->llvm_only && !call_target && virtual_ && (method->flags & METHOD_ATTRIBUTE_VIRTUAL))
return emit_llvmonly_virtual_call (cfg, method, sig, 0, args);
- need_unbox_trampoline = method->klass == mono_defaults.object_class || (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
+ need_unbox_trampoline = method->klass == mono_defaults.object_class || mono_class_is_interface (method->klass);
call = mono_emit_call_args (cfg, sig, args, FALSE, virtual_, tail, rgctx_arg ? TRUE : FALSE, need_unbox_trampoline);
} else {
vtable_reg = alloc_preg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, this_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
- if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (method->klass)) {
guint32 imt_slot = mono_method_get_imt_slot (method);
emit_imt_argument (cfg, call, call->method, imt_arg);
slot_reg = vtable_reg;
EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
alloc_ftn = ves_icall_object_new;
- } else if (cfg->compile_aot && cfg->cbb->out_of_line && klass->type_token && klass->image == mono_defaults.corlib && !klass->generic_class) {
+ } else if (cfg->compile_aot && cfg->cbb->out_of_line && klass->type_token && klass->image == mono_defaults.corlib && !mono_class_is_ginst (klass)) {
/* This happens often in argument checking code, eg. throw new FooException... */
/* Avoid relocations and save some space by calling a helper function specialized to mscorlib */
EMIT_NEW_ICONST (cfg, iargs [0], mono_metadata_token_index (klass->type_token));
MonoGenericContainer *container;
MonoGenericInst *ginst;
- if (klass->generic_class) {
- container = klass->generic_class->container_class->generic_container;
- ginst = klass->generic_class->context.class_inst;
- } else if (klass->generic_container && context_used) {
- container = klass->generic_container;
+ if (mono_class_is_ginst (klass)) {
+ container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
+ ginst = mono_class_get_generic_class (klass)->context.class_inst;
+ } else if (mono_class_is_gtd (klass) && context_used) {
+ container = mono_class_get_generic_container (klass);
ginst = container->context.class_inst;
} else {
return FALSE;
return FALSE;
}
-#define is_complex_isinst(klass) ((klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
+#define is_complex_isinst(klass) (mono_class_is_interface (klass) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || mono_class_is_sealed (klass) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
static MonoInst*
emit_isinst_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args)
save_cast_details (cfg, klass, obj_reg, FALSE);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
mini_emit_iface_cast (cfg, vtable_reg, klass, NULL, NULL);
} else {
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
- if (!klass->rank && !cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+ if (!klass->rank && !cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && mono_class_is_sealed (klass)) {
/* the remoting code is broken, access the class for now */
if (0) { /*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/
MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
g_assert (!context_used);
/* the is_null_bb target simply copies the input register to the output */
mini_emit_iface_cast (cfg, vtable_reg, klass, false_bb, is_null_bb);
} else if (klass->cast_class == mono_defaults.enum_class) {
mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb);
- } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ } else if (mono_class_is_interface (klass->cast_class)) {
mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb);
} else {
if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
/* the is_null_bb target simply copies the input register to the output */
mini_emit_isninst_cast (cfg, klass_reg, klass->cast_class, false_bb, is_null_bb);
} else {
- if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+ if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && mono_class_is_sealed (klass)) {
g_assert (!context_used);
/* the remoting code is broken, access the class for now */
if (0) {/*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, false_bb);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
#ifndef DISABLE_REMOTING
NEW_BBLOCK (cfg, interface_fail_bb);
#endif
save_cast_details (cfg, klass, obj_reg, FALSE);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
#ifndef DISABLE_REMOTING
NEW_BBLOCK (cfg, interface_fail_bb);
* This is hard to do with the current call code, since we would have to emit a branch and two different calls. So instead, we
* pack the arguments into an array, and do the rest of the work in in an icall.
*/
- if (((cmethod->klass == mono_defaults.object_class) || (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
+ if (((cmethod->klass == mono_defaults.object_class) || mono_class_is_interface (cmethod->klass) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
(MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mini_is_gsharedvt_type (fsig->ret)) &&
(fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1) || (fsig->param_count == 1 && (MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]))))) {
MonoInst *args [16];
return FALSE;
}
}
- } else if (method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
+ } else if (mono_class_is_before_field_init (method->klass)) {
if (cfg->run_cctors && method->klass->has_cctor) {
/*FIXME it would easier and lazier to just use mono_class_try_get_vtable */
if (!method->klass->runtime_info)
* the cctor will need to be run at aot method load time, for example,
* or at the end of the compilation of the inlining method.
*/
- if (mono_class_needs_cctor_run (method->klass, NULL) && !((method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+ if (mono_class_needs_cctor_run (method->klass, NULL) && !mono_class_is_before_field_init (method->klass))
return FALSE;
}
return FALSE;
}
- if (klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
+ if (mono_class_is_before_field_init (klass)) {
if (cfg->method == method)
return FALSE;
}
MonoInst *icall_args [16];
MonoInst *call_target, *ins, *vtable_ins;
int arg_reg, this_reg, vtable_reg;
- gboolean is_iface = cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE;
+ gboolean is_iface = mono_class_is_interface (cmethod->klass);
gboolean is_gsharedvt = cfg->gsharedvt && mini_is_gsharedvt_variable_signature (fsig);
gboolean variant_iface = FALSE;
guint32 slot;
return FALSE;
}
- attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
+ attrs = mono_custom_attrs_from_assembly_checked (ass, FALSE, &error);
mono_error_cleanup (&error); /* FIXME don't swallow the error */
if (attrs) {
for (i = 0; i < attrs->num_attrs; ++i) {
n = fsig->param_count + fsig->hasthis;
- if (!cfg->gshared && cmethod->klass->generic_container)
+ if (!cfg->gshared && mono_class_is_gtd (cmethod->klass))
UNVERIFIED;
if (!cfg->gshared)
if (mini_is_gsharedvt_klass (constrained_class)) {
if ((cmethod->klass != mono_defaults.object_class) && constrained_class->valuetype && cmethod->klass->valuetype) {
/* The 'Own method' case below */
- } else if (cmethod->klass->image != mono_defaults.corlib && !(cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && !cmethod->klass->valuetype) {
+ } else if (cmethod->klass->image != mono_defaults.corlib && !mono_class_is_interface (cmethod->klass) && !cmethod->klass->valuetype) {
/* 'The type parameter is instantiated as a reference type' case below. */
} else {
ins = handle_constrained_gsharedvt_call (cfg, cmethod, fsig, sp, constrained_class, &emit_widen);
* A simple solution would be to box always and make a normal virtual call, but that would
* be bad performance wise.
*/
- if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE && cmethod->klass->generic_class) {
+ if (mono_class_is_interface (cmethod->klass) && mono_class_is_ginst (cmethod->klass)) {
/*
* The parent classes implement no generic interfaces, so the called method will be a vtype method, so no boxing neccessary.
*/
nonbox_call->dreg = ins->dreg;
goto call_end;
} else {
- g_assert (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
+ g_assert (mono_class_is_interface (cmethod->klass));
addr = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_CODE);
ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
goto call_end;
* If the callee is a shared method, then its static cctor
* might not get called after the call was patched.
*/
- if (cfg->gshared && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
+ if (cfg->gshared && cmethod->klass != method->klass && mono_class_is_ginst (cmethod->klass) && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
emit_class_init (cfg, cmethod->klass);
CHECK_TYPELOAD (cmethod->klass);
}
context_used = mini_method_check_context_used (cfg, cmethod);
- if (context_used && (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ if (context_used && mono_class_is_interface (cmethod->klass)) {
/* Generic method interface
calls are resolved via a
helper function and don't
* This needs to be used for all generic calls, not just ones with a gsharedvt signature, to avoid
* patching gshared method addresses into a gsharedvt method.
*/
- if (cfg->gsharedvt && (mini_is_gsharedvt_signature (fsig) || cmethod->is_inflated || cmethod->klass->generic_class) &&
+ if (cfg->gsharedvt && (mini_is_gsharedvt_signature (fsig) || cmethod->is_inflated || mono_class_is_ginst (cmethod->klass)) &&
!(cmethod->klass->rank && cmethod->klass->byval_arg.type != MONO_TYPE_SZARRAY) &&
(!(cfg->llvm_only && virtual_ && (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL)))) {
MonoRgctxInfoType info_type;
if (virtual_) {
- //if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+ //if (mono_class_is_interface (cmethod->klass))
//GSHAREDVT_FAILURE (*ip);
// disable for possible remoting calls
if (fsig->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class))
cmethod, MONO_RGCTX_INFO_METHOD);
/* This is not needed, as the trampoline code will pass one, and it might be passed in the same reg as the imt arg */
vtable_arg = NULL;
- } else if ((cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && !imt_arg) {
+ } else if (mono_class_is_interface (cmethod->klass) && !imt_arg) {
/* This can happen when we call a fully instantiated iface method */
imt_arg = emit_get_rgctx_method (cfg, context_used,
cmethod, MONO_RGCTX_INFO_METHOD);
if (mono_security_core_clr_enabled ())
ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
- if (cfg->gshared && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
+ if (cfg->gshared && cmethod && cmethod->klass != method->klass && mono_class_is_ginst (cmethod->klass) && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
emit_class_init (cfg, cmethod->klass);
CHECK_TYPELOAD (cmethod->klass);
}
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), const_ins->dreg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_ins->dreg, MONO_STRUCT_OFFSET (MonoClass, byval_arg));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
- } else if (cfg->compile_aot) {
+ } else {
int const_reg = alloc_preg (cfg);
int type_reg = alloc_preg (cfg);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), const_reg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_reg, MONO_STRUCT_OFFSET (MonoClass, byval_arg));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
- } else {
- MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREP_MEMBASE_IMM, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), &klass->byval_arg);
- MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREP_MEMBASE_IMM, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), klass);
}
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, value), sp [0]->dreg);
ret = emit_isinst_with_cache_nonshared (cfg, source, klass);
else
ret = emit_castclass_with_cache_nonshared (cfg, source, klass);
- } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ } else if (!context_used && (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass))) {
MonoInst *iargs [1];
int costs;
static int i8_align;
static gpointer single_step_tramp, breakpoint_tramp;
+static gpointer get_tls_tramp;
/*
* The code generated for sequence points reads from this location, which is
static void mono_arch_compute_omit_fp (MonoCompile *cfg);
#endif
+static guint8*
+emit_aotconst (MonoCompile *cfg, guint8 *code, int dreg, int patch_type, gpointer data);
+
const char*
mono_arch_regname (int reg)
{
{
#ifdef HAVE_FAST_TLS
code = mono_arm_emit_load_imm (code, ARMREG_R0, tls_offset);
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- "mono_get_tls_key");
- code = emit_call_seq (cfg, code);
+ if (cfg->compile_aot) {
+ /*
+ * This opcode is generated by CEE_MONO_JIT_ATTACH, so it can execute on
+ * threads which are not yet attached to the runtime. This means we can't
+ * call it directly, since the call would go through the trampoline code
+ * which assumes the thread is attached. So use a separate patch info type
+ * for it, and load it from a preinitialized GOT slot.
+ */
+ code = emit_aotconst (cfg, code, ARMREG_R1, MONO_PATCH_INFO_GET_TLS_TRAMP, NULL);
+ code = emit_call_reg (code, ARMREG_R1);
+ } else {
+ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+ "mono_get_tls_key");
+ code = emit_call_seq (cfg, code);
+ }
if (dreg != ARMREG_R0)
ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
#else
#ifdef HAVE_FAST_TLS
if (tls_offset_reg != ARMREG_R0)
ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- "mono_get_tls_key");
- code = emit_call_seq (cfg, code);
+ if (cfg->compile_aot) {
+ code = emit_aotconst (cfg, code, ARMREG_R1, MONO_PATCH_INFO_GET_TLS_TRAMP, NULL);
+ code = emit_call_reg (code, ARMREG_R1);
+ } else {
+ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+ "mono_get_tls_key");
+ code = emit_call_seq (cfg, code);
+ }
if (dreg != ARMREG_R0)
ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
#else
mono_register_jit_icall (tls_imp.get_tls_thunk, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE);
mono_register_jit_icall (tls_imp.set_tls_thunk, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE);
+ get_tls_tramp = tls_imp.get_tls_thunk;
+
if (tls_imp.get_tls_thunk_end) {
mono_tramp_info_register (
mono_tramp_info_create (
{
return get_call_info (mp, sig);
}
+
+gpointer
+mono_arch_get_get_tls_tramp (void)
+{
+ return get_tls_tramp;
+}
+
+static guint8*
+emit_aotconst (MonoCompile *cfg, guint8 *code, int dreg, int patch_type, gpointer data)
+{
+ /* OP_AOTCONST */
+ mono_add_patch_info (cfg, code - cfg->native_code, patch_type, data);
+ ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
+ ARM_B (code, 0);
+ *(gpointer*)code = NULL;
+ code += 4;
+ /* Load the value from the GOT */
+ ARM_LDR_REG_REG (code, dreg, ARMREG_PC, dreg);
+ return code;
+}
#define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
#define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
#define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1
+#define MONO_ARCH_HAVE_GET_TLS_TRAMP 1
#define MONO_ARCH_HAVE_TLS_GET (mono_arm_have_tls_get ())
#define MONO_ARCH_HAVE_TLS_GET_REG 1
* (C) 2003 Ximian, Inc.
*/
+#include "config.h"
+
#include <string.h>
#include <math.h>
#ifdef HAVE_UNISTD_H
#include "trace.h"
#include "mini-arch.h"
+#ifndef DISABLE_JIT
+
#ifndef MONO_MAX_XREGS
#define MONO_MAX_XREGS 0
#define MONO_ARCH_CALLEE_XREGS 0
#endif
-
#define MONO_ARCH_BANK_MIRRORED -2
regmask_t preferred_mask; /* the hreg where the register should be allocated, or 0 */
} RegTrack;
-#if !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT)
-
-static const char* const patch_info_str[] = {
-#define PATCH_INFO(a,b) "" #a,
-#include "patch-info.h"
-#undef PATCH_INFO
-};
-
-const char*
-mono_ji_type_to_string (MonoJumpInfoType type)
-{
- return patch_info_str [type];
-}
-
-void
-mono_print_ji (const MonoJumpInfo *ji)
-{
- switch (ji->type) {
- case MONO_PATCH_INFO_RGCTX_FETCH: {
- MonoJumpInfoRgctxEntry *entry = ji->data.rgctx_entry;
-
- printf ("[RGCTX_FETCH ");
- mono_print_ji (entry->data);
- printf (" - %s]", mono_rgctx_info_type_to_str (entry->info_type));
- break;
- }
- case MONO_PATCH_INFO_METHODCONST: {
- char *s = mono_method_full_name (ji->data.method, TRUE);
- printf ("[METHODCONST - %s]", s);
- g_free (s);
- break;
- }
- case MONO_PATCH_INFO_INTERNAL_METHOD: {
- printf ("[INTERNAL_METHOD - %s]", ji->data.name);
- break;
- }
- default:
- printf ("[%s]", patch_info_str [ji->type]);
- break;
- }
-}
+#if !defined(DISABLE_LOGGING)
void
mono_print_ins_index (int i, MonoInst *ins)
}
#else
-const char*
-mono_ji_type_to_string (MonoJumpInfoType type)
-{
- return "";
-}
-
-void
-mono_print_ji (const MonoJumpInfo *ji)
-{
-}
-
void
mono_print_ins_index (int i, MonoInst *ins)
{
}
-#endif /* !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT) */
+#endif /* !defined(DISABLE_LOGGING) */
void
mono_print_ins (MonoInst *ins)
static gint8 desc_to_fixed_reg [256];
static gboolean desc_to_fixed_reg_inited = FALSE;
-#ifndef DISABLE_JIT
-
/*
* Local register allocation.
* We first scan the list of instructions and we save the liveness info of
}
}
-#endif /* DISABLE_JIT */
-
-gboolean
-mono_is_regsize_var (MonoType *t)
-{
- t = mini_get_underlying_type (t);
- switch (t->type) {
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
-#if SIZEOF_REGISTER == 8
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
-#endif
- return TRUE;
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- return TRUE;
- case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (t))
- return TRUE;
- return FALSE;
- case MONO_TYPE_VALUETYPE:
- return FALSE;
- default:
- return FALSE;
- }
-}
-
-#ifndef DISABLE_JIT
-
/*
* mono_peephole_ins:
*
}
#endif /* DISABLE_JIT */
+
+gboolean
+mono_is_regsize_var (MonoType *t)
+{
+ t = mini_get_underlying_type (t);
+ switch (t->type) {
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_FNPTR:
+#if SIZEOF_REGISTER == 8
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+#endif
+ return TRUE;
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_ARRAY:
+ return TRUE;
+ case MONO_TYPE_GENERICINST:
+ if (!mono_type_generic_inst_is_valuetype (t))
+ return TRUE;
+ return FALSE;
+ case MONO_TYPE_VALUETYPE:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
{
kern_return_t ret;
- mach_msg_type_number_t num_state;
- thread_state_t state;
+ mach_msg_type_number_t num_state, num_fpstate;
+ thread_state_t state, fpstate;
ucontext_t ctx;
mcontext_t mctx;
MonoJitTlsData *jit_tls;
tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL;
state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ());
+ fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ());
mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ());
do {
- ret = mono_mach_arch_get_thread_state (info->native_handle, state, &num_state);
+ ret = mono_mach_arch_get_thread_states (info->native_handle, state, &num_state, fpstate, &num_fpstate);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
return FALSE;
- mono_mach_arch_thread_state_to_mcontext (state, mctx);
+ mono_mach_arch_thread_states_to_mcontext (state, fpstate, mctx);
ctx.uc_mcontext = mctx;
mono_sigctx_to_monoctx (&ctx, &tctx->ctx);
klass = vtable->klass;
}
- //g_assert (!method->klass->generic_container);
- if (method->klass->generic_class)
- method_container_class = method->klass->generic_class->container_class;
+ //g_assert (!mono_class_is_gtd (method->klass));
+ if (mono_class_is_ginst (method->klass))
+ method_container_class = mono_class_get_generic_class (method->klass)->container_class;
else
method_container_class = method->klass;
/* class might refer to a subclass of method's class */
- while (!(klass == method->klass || (klass->generic_class && klass->generic_class->container_class == method_container_class))) {
+ while (!(klass == method->klass || (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->container_class == method_container_class))) {
klass = klass->parent;
g_assert (klass);
}
- if (klass->generic_class || klass->generic_container)
+ if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
context.class_inst = mini_class_get_context (klass)->class_inst;
- if (klass->generic_class)
- g_assert (mono_class_has_parent_and_ignore_generics (klass->generic_class->container_class, method_container_class));
+ if (mono_class_is_ginst (klass))
+ g_assert (mono_class_has_parent_and_ignore_generics (mono_class_get_generic_class (klass)->container_class, method_container_class));
else
g_assert (mono_class_has_parent_and_ignore_generics (klass, method_container_class));
klass = mono_class_get_runtime_compat_attr_class ();
- attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
+ attrs = mono_custom_attrs_from_assembly_checked (ass, FALSE, &error);
mono_error_cleanup (&error); /* FIXME don't swallow the error */
if (attrs) {
for (i = 0; i < attrs->num_attrs; ++i) {
if (recursive) {
MonoGenericClass *gclass = type->data.generic_class;
- g_assert (gclass->container_class->generic_container);
+ g_assert (mono_class_is_gtd (gclass->container_class));
return mono_generic_context_check_used (&gclass->context);
} else {
return 0;
context_used |= type_check_context_used (&klass->this_arg, FALSE);
context_used |= type_check_context_used (&klass->byval_arg, FALSE);
- if (klass->generic_class)
- context_used |= mono_generic_context_check_used (&klass->generic_class->context);
- else if (klass->generic_container)
- context_used |= mono_generic_context_check_used (&klass->generic_container->context);
+ if (mono_class_is_ginst (klass))
+ context_used |= mono_generic_context_check_used (&mono_class_get_generic_class (klass)->context);
+ else if (mono_class_is_gtd (klass))
+ context_used |= mono_generic_context_check_used (&mono_class_get_generic_container (klass)->context);
return context_used;
}
g_assert (rgctx_template);
- if (parent->generic_class)
- parent = parent->generic_class->container_class;
+ if (mono_class_is_ginst (parent))
+ parent = mono_class_get_generic_class (parent)->container_class;
if (!generic_subclass_hash)
generic_subclass_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
declaring = method;
m = NULL;
- if (klass->generic_class)
+ if (mono_class_is_ginst (klass))
m = mono_class_get_inflated_method (klass, declaring);
if (!m) {
static MonoClass*
class_uninstantiated (MonoClass *klass)
{
- if (klass->generic_class)
- return klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ return mono_class_get_generic_class (klass)->container_class;
return klass;
}
DEBUG (printf ("get slot: %s %d\n", mono_type_full_name (&class->byval_arg), slot));
- if (klass->generic_class && !shared) {
+ if (mono_class_is_ginst (klass) && !shared) {
MonoRuntimeGenericContextInfoTemplate oti;
gboolean tmp_do_free;
- oti = class_get_rgctx_template_oti (klass->generic_class->container_class,
+ oti = class_get_rgctx_template_oti (mono_class_get_generic_class (klass)->container_class,
type_argc, slot, TRUE, FALSE, &tmp_do_free);
if (oti.data) {
gpointer info = oti.data;
- oti.data = inflate_info (&oti, &klass->generic_class->context, klass, temporary);
+ oti.data = inflate_info (&oti, &mono_class_get_generic_class (klass)->context, klass, temporary);
if (tmp_do_free)
free_inflated_info (oti.info_type, info);
}
return get_wrapper_shared_type (&mono_defaults.object_class->byval_arg);
klass = mono_class_from_mono_type (t);
- orig_ctx = &klass->generic_class->context;
+ orig_ctx = &mono_class_get_generic_class (klass)->context;
memset (&ctx, 0, sizeof (MonoGenericContext));
args [i] = get_wrapper_shared_type (inst->type_argv [i]);
ctx.method_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
}
- klass = mono_class_inflate_generic_class_checked (klass->generic_class->container_class, &ctx, &error);
+ klass = mono_class_inflate_generic_class_checked (mono_class_get_generic_class (klass)->container_class, &ctx, &error);
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
return &klass->byval_arg;
}
MonoMethod *res, *cached;
WrapperInfo *info;
MonoMethodSignature *csig, *gsharedvt_sig;
- int i, pindex, retval_var;
+ int i, pindex, retval_var = 0;
static GHashTable *cache;
// FIXME: Memory management
mono_class_setup_vtable (info->klass);
// FIXME: Check type load
- if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (iface_class)) {
ioffset = mono_class_interface_offset (info->klass, iface_class);
g_assert (ioffset != -1);
} else {
mono_class_setup_vtable (info->klass);
// FIXME: Check type load
- if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (iface_class)) {
ioffset = mono_class_interface_offset (info->klass, iface_class);
g_assert (ioffset != -1);
} else {
/* See mono_emit_method_call_full () */
/* The gsharedvt trampoline will recognize this constant */
vcall_offset = MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET;
- } else if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ } else if (mono_class_is_interface (method->klass)) {
guint32 imt_slot = mono_method_get_imt_slot (method);
vcall_offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
} else {
MonoRuntimeGenericContextTemplate *parent_template;
MonoRuntimeGenericContextInfoTemplate *oti;
- if (parent->generic_class)
- parent = parent->generic_class->container_class;
+ if (mono_class_is_ginst (parent))
+ parent = mono_class_get_generic_class (parent)->container_class;
parent_template = mono_class_get_runtime_generic_context_template (parent);
oti = rgctx_template_get_other_slot (parent_template, type_argc, i);
int i, first_slot, size;
MonoDomain *domain = class_vtable->domain;
MonoClass *klass = class_vtable->klass;
- MonoGenericContext *class_context = klass->generic_class ? &klass->generic_class->context : NULL;
+ MonoGenericContext *class_context = mono_class_is_ginst (klass) ? &mono_class_get_generic_class (klass)->context : NULL;
MonoRuntimeGenericContextInfoTemplate oti;
MonoGenericContext context = { class_context ? class_context->class_inst : NULL, method_inst };
int rgctx_index;
MonoMethodRuntimeGenericContext *mrgctx;
MonoMethodRuntimeGenericContext key;
- g_assert (!class_vtable->klass->generic_container);
+ g_assert (!mono_class_is_gtd (class_vtable->klass));
g_assert (!method_inst->is_open);
mono_domain_lock (domain);
if not compiled with sharing. */
if (method->wrapper_type != MONO_WRAPPER_NONE)
return FALSE;
- if (method->klass->generic_container)
+ if (mono_class_is_gtd (method->klass))
return TRUE;
return FALSE;
}
}
}
- if (method->klass->generic_class) {
- if (!mono_generic_context_is_sharable_full (&method->klass->generic_class->context, allow_type_vars, allow_partial))
+ if (mono_class_is_ginst (method->klass)) {
+ if (!mono_generic_context_is_sharable_full (&mono_class_get_generic_class (method->klass)->context, allow_type_vars, allow_partial))
return FALSE;
- g_assert (method->klass->generic_class->container_class &&
- method->klass->generic_class->container_class->generic_container);
+ g_assert (mono_class_get_generic_class (method->klass)->container_class &&
+ mono_class_is_gtd (mono_class_get_generic_class (method->klass)->container_class));
- if (has_constraints (method->klass->generic_class->container_class->generic_container))
+ if (has_constraints (mono_class_get_generic_container (mono_class_get_generic_class (method->klass)->container_class)))
return FALSE;
}
- if (method->klass->generic_container && !allow_type_vars)
+ if (mono_class_is_gtd (method->klass) && !allow_type_vars)
return FALSE;
/* This does potentially expensive cattr checks, so do it at the end */
return ((method->flags & METHOD_ATTRIBUTE_STATIC) ||
method->klass->valuetype) &&
- (method->klass->generic_class || method->klass->generic_container);
+ (mono_class_is_ginst (method->klass) || mono_class_is_gtd (method->klass));
}
static MonoGenericInst*
{
MonoGenericContext object_context;
- g_assert (!method->klass->generic_class);
- if (method->klass->generic_container) {
- int type_argc = method->klass->generic_container->type_argc;
+ g_assert (!mono_class_is_ginst (method->klass));
+ if (mono_class_is_gtd (method->klass)) {
+ int type_argc = mono_class_get_generic_container (method->klass)->type_argc;
object_context.class_inst = get_object_generic_inst (type_argc);
} else {
MonoClass*
mini_class_get_container_class (MonoClass *klass)
{
- if (klass->generic_class)
- return klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ return mono_class_get_generic_class (klass)->container_class;
- g_assert (klass->generic_container);
+ g_assert (mono_class_is_gtd (klass));
return klass;
}
MonoGenericContext*
mini_class_get_context (MonoClass *klass)
{
- if (klass->generic_class)
- return &klass->generic_class->context;
+ if (mono_class_is_ginst (klass))
+ return &mono_class_get_generic_class (klass)->context;
- g_assert (klass->generic_container);
- return &klass->generic_container->context;
+ g_assert (mono_class_is_gtd (klass));
+ return &mono_class_get_generic_container (klass)->context;
}
/*
gboolean
mini_class_is_generic_sharable (MonoClass *klass)
{
- if (klass->generic_class && is_async_state_machine_class (klass))
+ if (mono_class_is_ginst (klass) && is_async_state_machine_class (klass))
return FALSE;
- return (klass->generic_class && mono_generic_context_is_sharable (&klass->generic_class->context, FALSE));
+ return (mono_class_is_ginst (klass) && mono_generic_context_is_sharable (&mono_class_get_generic_class (klass)->context, FALSE));
}
gboolean
memset (&context, 0, sizeof (context));
if (gclass->context.class_inst)
- context.class_inst = get_shared_inst (gclass->context.class_inst, gclass->container_class->generic_container->context.class_inst, NULL, FALSE, FALSE, TRUE);
+ context.class_inst = get_shared_inst (gclass->context.class_inst, mono_class_get_generic_container (gclass->container_class)->context.class_inst, NULL, FALSE, FALSE, TRUE);
if (gclass->context.method_inst)
- context.method_inst = get_shared_inst (gclass->context.method_inst, gclass->container_class->generic_container->context.method_inst, NULL, FALSE, FALSE, TRUE);
+ context.method_inst = get_shared_inst (gclass->context.method_inst, mono_class_get_generic_container (gclass->container_class)->context.method_inst, NULL, FALSE, FALSE, TRUE);
k = mono_class_inflate_generic_class_checked (gclass->container_class, &context, &error);
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
}
}
- if (method->is_generic || (method->klass->generic_container && !method->is_inflated)) {
+ if (method->is_generic || (mono_class_is_gtd (method->klass) && !method->is_inflated)) {
declaring_method = method;
} else {
declaring_method = mono_method_get_declaring_generic_method (method);
if (declaring_method->is_generic)
shared_context = mono_method_get_generic_container (declaring_method)->context;
else
- shared_context = declaring_method->klass->generic_container->context;
+ shared_context = mono_class_get_generic_container (declaring_method->klass)->context;
if (!is_gsharedvt)
partial = mono_method_is_generic_sharable_full (method, FALSE, TRUE, FALSE);
gsharedvt = is_gsharedvt || (!partial && mini_is_gsharedvt_sharable_method (method));
- class_container = declaring_method->klass->generic_container;
+ class_container = mono_class_try_get_generic_container (declaring_method->klass); //FIXME is this a case for a try_get?
method_container = mono_method_get_generic_container (declaring_method);
/*
mono_llvm_set_call_notail (LLVMValueRef func)
{
#if LLVM_API_VERSION > 100
- //unwrap<CallInst>(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail);
+ unwrap<CallInst>(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail);
#endif
}
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
-#include "mini.h"
+#include "config.h"
+
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/debug-mono-symfile.h>
#include <mono/metadata/mempool-internals.h>
#include "aot-compiler.h"
#include "mini-llvm.h"
+#ifndef DISABLE_JIT
+
#ifdef __MINGW32__
#include <stddef.h>
lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
+ if (ins->opcode != OP_TAILCALL && LLVMGetInstructionOpcode (lcall) == LLVMCall)
+ mono_llvm_set_call_notail (lcall);
+
/*
* Modify cconv and parameter attributes to pass rgctx/imt correctly.
*/
* code.
* - use pointer types to help optimizations.
*/
+
+#else /* DISABLE_JIT */
+
+void
+mono_llvm_cleanup (void)
+{
+}
+
+void
+mono_llvm_free_domain_info (MonoDomain *domain)
+{
+}
+
+void
+mono_llvm_init (void)
+{
+}
+
+void
+default_mono_llvm_unhandled_exception (void)
+{
+}
+
+#endif /* DISABLE_JIT */
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/checked-build.h>
-#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32handle.h>
#include <mono/io-layer/io-layer.h>
#include "mini.h"
return ji;
}
+#if !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT)
+
+static const char* const patch_info_str[] = {
+#define PATCH_INFO(a,b) "" #a,
+#include "patch-info.h"
+#undef PATCH_INFO
+};
+
+const char*
+mono_ji_type_to_string (MonoJumpInfoType type)
+{
+ return patch_info_str [type];
+}
+
+void
+mono_print_ji (const MonoJumpInfo *ji)
+{
+ switch (ji->type) {
+ case MONO_PATCH_INFO_RGCTX_FETCH: {
+ MonoJumpInfoRgctxEntry *entry = ji->data.rgctx_entry;
+
+ printf ("[RGCTX_FETCH ");
+ mono_print_ji (entry->data);
+ printf (" - %s]", mono_rgctx_info_type_to_str (entry->info_type));
+ break;
+ }
+ case MONO_PATCH_INFO_METHODCONST: {
+ char *s = mono_method_full_name (ji->data.method, TRUE);
+ printf ("[METHODCONST - %s]", s);
+ g_free (s);
+ break;
+ }
+ case MONO_PATCH_INFO_INTERNAL_METHOD: {
+ printf ("[INTERNAL_METHOD - %s]", ji->data.name);
+ break;
+ }
+ default:
+ printf ("[%s]", patch_info_str [ji->type]);
+ break;
+ }
+}
+
+#else
+
+const char*
+mono_ji_type_to_string (MonoJumpInfoType type)
+{
+ return "";
+}
+
+void
+mono_print_ji (const MonoJumpInfo *ji)
+{
+}
+
+#endif
+
/**
* mono_patch_info_dup_mp:
*
case MONO_PATCH_INFO_GOT_OFFSET:
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
case MONO_PATCH_INFO_AOT_MODULE:
+ case MONO_PATCH_INFO_GET_TLS_TRAMP:
return (ji->type << 8);
case MONO_PATCH_INFO_CASTCLASS_CACHE:
return (ji->type << 8) | (ji->data.index);
break;
case MONO_PATCH_INFO_IID:
mono_class_init (patch_info->data.klass);
- target = GINT_TO_POINTER ((int)patch_info->data.klass->interface_id);
+ target = GUINT_TO_POINTER (patch_info->data.klass->interface_id);
break;
case MONO_PATCH_INFO_ADJUSTED_IID:
mono_class_init (patch_info->data.klass);
- target = GINT_TO_POINTER ((int)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P)));
+ target = GUINT_TO_POINTER ((guint32)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P)));
break;
case MONO_PATCH_INFO_VTABLE:
target = mono_class_vtable (domain, patch_info->data.klass);
}
g_assert (vtable);
- if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
+ if (!vtable->initialized && !mono_class_is_before_field_init (vtable->klass) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
/* Done by the generated code */
;
else {
case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
break;
+ case MONO_PATCH_INFO_GET_TLS_TRAMP:
+#ifdef MONO_ARCH_HAVE_GET_TLS_TRAMP
+ target = mono_arch_get_get_tls_tramp ();
+#else
+ target = NULL;
+#endif
+ break;
default:
g_assert_not_reached ();
}
if ((code = mono_aot_get_method_checked (domain, method, error))) {
MonoVTable *vtable;
+ if (mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method)) {
+ /*
+ * The suspend code needs to be able to lookup these methods by ip in async context,
+ * so preload their jit info.
+ */
+ MonoJitInfo *ji = mono_jit_info_table_find (domain, code);
+ g_assert (ji);
+ }
+
/*
* In llvm-only mode, method might be a shared method, so we can't initialize its class.
* This is not a problem, since it will be initialized when the method is first
return NULL;
is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
- is_interface = method->klass->flags & TYPE_ATTRIBUTE_INTERFACE ? TRUE : FALSE;
+ is_interface = mono_class_is_interface (method->klass);
load_imt_reg = is_virtual_generic || is_interface;
if (is_interface)
}
if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
continue;
- if (method->is_generic || method->klass->generic_container)
+ if (method->is_generic || mono_class_is_gtd (method->klass))
continue;
count++;
ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
printf (" ip: %p\n", (gpointer) ip);
+ va_end (ap);
}
/*========================= End of Function ========================*/
/* imt_method->slot might not be set */
impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot);
- if (impl->klass->generic_class)
- context.class_inst = impl->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (impl->klass))
+ context.class_inst = mono_class_get_generic_class (impl->klass)->context.class_inst;
context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst;
impl = mono_class_inflate_generic_method_checked (impl, &context, error);
mono_error_assert_ok (error);
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
generic_virtual = mono_arch_find_imt_method (regs, code);
g_assert (generic_virtual);
else
declaring = m;
- if (klass->generic_class)
- context.class_inst = klass->generic_class->context.class_inst;
- else if (klass->generic_container)
- context.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (klass))
+ context.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
+ else if (mono_class_is_gtd (klass))
+ context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
context.method_inst = method_inst;
actual_method = mono_class_inflate_generic_method_checked (declaring, &context, error);
gpointer *vtable_slot;
MonoMethod *m;
MonoError error;
- gpointer addr, res;
+ gpointer addr, res = NULL;
trampoline_calls ++;
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
imt_method = mono_arch_find_imt_method (regs, code);
if (imt_method->is_inflated)
* If the call doesn't return a valuetype, then the vcall uses the same calling
* convention as a normal call.
*/
- if (((method->klass->flags & TYPE_ATTRIBUTE_SEALED) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
+ if ((mono_class_is_sealed (method->klass) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
callvirt = FALSE;
enable_caching = FALSE;
}
if (delegate->target &&
method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
method->flags & METHOD_ATTRIBUTE_ABSTRACT &&
- method->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) {
+ mono_class_is_abstract (method->klass)) {
method = mono_object_get_virtual_method (delegate->target, method);
enable_caching = FALSE;
}
gboolean is_generic = FALSE;
if (cfg->method->is_inflated || mono_method_get_generic_container (cfg->method) ||
- cfg->method->klass->generic_container || cfg->method->klass->generic_class) {
+ mono_class_is_gtd (cfg->method->klass) || mono_class_is_ginst (cfg->method->klass)) {
is_generic = TRUE;
}
cfg->seq_points = g_ptr_array_new ();
mono_error_init (&cfg->error);
- if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container || method_is_gshared)) {
+ if (cfg->compile_aot && !try_generic_shared && (method->is_generic || mono_class_is_gtd (method->klass) || method_is_gshared)) {
cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;
return cfg;
}
#define MONO_INS_IS_PCONST_NULL(ins) ((ins)->opcode == OP_PCONST && (ins)->inst_p0 == 0)
-#define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && ((m)->klass->flags & TYPE_ATTRIBUTE_SEALED)))
+#define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && (mono_class_get_flags ((m)->klass) & TYPE_ATTRIBUTE_SEALED)))
#ifdef MONO_ARCH_SIMD_INTRINSICS
gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot);
gpointer mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot);
guint8 *mono_arch_create_llvm_native_thunk (MonoDomain *domain, guint8* addr) MONO_LLVM_INTERNAL;
+gpointer mono_arch_get_get_tls_tramp (void);
GList *mono_arch_get_allocatable_int_vars (MonoCompile *cfg);
GList *mono_arch_get_global_int_regs (MonoCompile *cfg);
GList *mono_arch_get_global_fp_regs (MonoCompile *cfg);
PATCH_INFO(GC_NURSERY_BITS, "gc_nursery_bits")
PATCH_INFO(GSHAREDVT_IN_WRAPPER, "gsharedvt_in_wrapper")
PATCH_INFO(ICALL_ADDR_CALL, "icall_addr_call")
+PATCH_INFO(GET_TLS_TRAMP, "get_tls_tramp")
switch (op->op){
case MONO_TRACEOP_ALL:
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_PROGRAM:
if (trace_spec.assembly && (method->klass->image == mono_assembly_get_image (trace_spec.assembly)))
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_WRAPPER:
if ((method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) ||
(method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE))
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_METHOD:
if (mono_method_desc_full_match ((MonoMethodDesc *) op->data, method))
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_CLASS:
if (strcmp (method->klass->name_space, op->data) == 0)
if (strcmp (method->klass->name, op->data2) == 0)
break;
case MONO_TRACEOP_ASSEMBLY:
if (strcmp (mono_image_get_name (method->klass->image), op->data) == 0)
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_NAMESPACE:
if (strcmp (method->klass->name_space, op->data) == 0)
inc = 1;
+ break;
case MONO_TRACEOP_EXCEPTION:
break;
}
- if (op->exclude){
+ if (op->exclude) {
if (inc)
include = 0;
- } else if (inc)
+ } else if (inc) {
include = 1;
+ }
}
return include;
}
guint8*
mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gboolean aot)
{
- int tramp_size = 256;
+ int tramp_size = 512;
int i, framesize, ctx_offset, cfa_offset, gregs_offset;
guint8 *code, *buf;
GSList *unwind_ops = NULL;
return GPOINTER_TO_UINT (ptr) >> 3;
}
-#define SGEN_PTR_IN_NURSERY(p,bits,start,end) (((mword)(p) & ~((1 << (bits)) - 1)) == (mword)(start))
+#define SGEN_PTR_IN_NURSERY(p,bits,start,end) (((mword)(p) & ~(((mword)1 << (bits)) - 1)) == (mword)(start))
#ifdef USER_CONFIG
assembly-load-stress.cs
BASE_TEST_MOBILE_STATIC_NOT_SUPPORTED= \
- remoting4.cs # Needs remoting support \
- remoting1.cs # Needs remoting support \
- remoting2.cs # Needs remoting support \
- remoting3.cs # Needs remoting support \
- remoting5.cs # Needs remoting support \
- appdomain.cs # Needs appdomain support \
- appdomain-client.cs # Needs appdomain support \
- appdomain-unload.cs # Needs appdomain support \
- appdomain-async-invoke.cs # Needs appdomain support \
- appdomain-thread-abort.cs # Needs appdomain support \
- appdomain1.cs # Needs appdomain support \
- appdomain2.cs # Needs appdomain support \
- appdomain-exit.cs # Needs appdomain support \
- assemblyresolve_event2.2.cs # Needs appdomain support \
- appdomain-unload-callback.cs # Needs appdomain support \
- appdomain-unload-doesnot-raise-pending-events.cs # Needs appdomain support \
- unload-appdomain-on-shutdown.cs # Needs appdomain support \
- bug-47295.cs # Needs SRE \
- loader.cs # Needs SRE \
- pinvoke2.cs # Needs SRE \
- generic-type-builder.2.cs # Needs SRE \
- dynamic-generic-size.cs # Needs SRE \
- cominterop.cs # Needs COM \
- dynamic-method-access.2.cs # Need SRE \
- dynamic-method-finalize.2.cs # Need SRE \
- dynamic-method-stack-traces.cs # Need SRE\
- generic_type_definition.2.cs # Need SRE \
- bug-333798-tb.2.cs # Need SRE \
- bug-335131.2.cs # Need SRE \
- bug-322722_patch_bx.2.cs # Need SRE\
- bug-322722_dyn_method_throw.2.cs # Need SRE \
- bug-389886-2.cs # Need SRE \
- bug-349190.2.cs # Need SRE \
- bug-389886-sre-generic-interface-instances.cs # Need SRE \
- bug-462592.cs # Need SRE \
- bug-575941.cs # Need SRE \
- bug-389886-3.cs # Need SRE \
- constant-division.cs # Need SRE \
- dynamic-method-resurrection.cs # Need SRE \
- bug-80307.cs # Need System.Web \
- assembly_append_ordering.cs # Need SRE \
- bug-544446.cs # Needs AppDomains / TranparentProxy \
- bug-36848.cs # Needs AppDomains / TranparentProxy \
- generic-marshalbyref.2.cs # Needs AppDomains \
- stackframes-async.2.cs # Needs AppDomains \
- transparentproxy.cs # Needs AppDomains / TranparentProxy \
- bug-48015.cs # Needs AppDomains / TranparentProxy \
- delegate9.cs # Needs AppDomains \
- marshal-valuetypes.cs # Needs AppDomains \
- xdomain-threads.cs # Needs AppDomains \
- monitor.cs # Needs AppDomains \
- generic-xdomain.2.cs # Needs AppDomains \
- threadpool-exceptions7.cs # Needs AppDomains \
- cross-domain.cs # Needs AppDomains \
- generic-unloading.2.cs # Needs AppDomains \
- namedmutex-destroy-race.cs # needs named Mutex \
- thread6.cs # On MOBILE, ThreadAbortException doesn't have necessary field for this test
+ remoting4.cs \
+ remoting1.cs \
+ remoting2.cs \
+ remoting3.cs \
+ remoting5.cs \
+ appdomain.cs \
+ appdomain-client.cs \
+ appdomain-unload.cs \
+ appdomain-async-invoke.cs \
+ appdomain-thread-abort.cs \
+ appdomain1.cs \
+ appdomain2.cs \
+ appdomain-exit.cs \
+ assemblyresolve_event2.2.cs \
+ appdomain-unload-callback.cs \
+ appdomain-unload-doesnot-raise-pending-events.cs \
+ unload-appdomain-on-shutdown.cs \
+ bug-47295.cs \
+ loader.cs \
+ pinvoke2.cs \
+ generic-type-builder.2.cs \
+ dynamic-generic-size.cs \
+ cominterop.cs \
+ dynamic-method-access.2.cs \
+ dynamic-method-finalize.2.cs \
+ dynamic-method-stack-traces.cs \
+ generic_type_definition.2.cs \
+ bug-333798-tb.2.cs \
+ bug-335131.2.cs \
+ bug-322722_patch_bx.2.cs \
+ bug-322722_dyn_method_throw.2.cs \
+ bug-389886-2.cs \
+ bug-349190.2.cs \
+ bug-389886-sre-generic-interface-instances.cs \
+ bug-462592.cs \
+ bug-575941.cs \
+ bug-389886-3.cs \
+ constant-division.cs \
+ dynamic-method-resurrection.cs \
+ bug-80307.cs \
+ assembly_append_ordering.cs \
+ bug-544446.cs \
+ bug-36848.cs \
+ generic-marshalbyref.2.cs \
+ stackframes-async.2.cs \
+ transparentproxy.cs \
+ bug-48015.cs \
+ delegate9.cs \
+ marshal-valuetypes.cs \
+ xdomain-threads.cs \
+ monitor.cs \
+ generic-xdomain.2.cs \
+ threadpool-exceptions7.cs \
+ cross-domain.cs \
+ generic-unloading.2.cs \
+ namedmutex-destroy-race.cs \
+ thread6.cs \
+ appdomain-threadpool-unload.cs
# Disabled until ?mcs is fixed
# bug-331958.cs
bug-29585.cs \
priority.cs \
abort-cctor.cs \
- thread-native-exit.cs
+ thread-native-exit.cs \
+ reference-loader.cs \
+ thread-suspend-suspended.cs
if INSTALL_MOBILE_STATIC
BASE_TEST_CS_SRC= \
bug-459094.exe \
delegate-invoke.exe \
bug-Xamarin-5278.exe \
- reference-loader.cs \
$(PLATFORM_DISABLED_TESTS) \
$(EXTRA_DISABLED_TESTS) \
$(COOP_DISABLED_TESTS) \
bug-36848-a.dll$(PLATFORM_AOT_SUFFIX) \
bug-81691-b.dll$(PLATFORM_AOT_SUFFIX) \
bug-327438.2.exe$(PLATFORM_AOT_SUFFIX) \
-bug-81466-lib.dll$(PLATFORM_AOT_SUFFIX)
+bug-81466-lib.dll$(PLATFORM_AOT_SUFFIX) \
+TestingReferenceAssembly.dll$(PLATFORM_AOT_SUFFIX) \
+TestingReferenceReferenceAssembly.dll$(PLATFORM_AOT_SUFFIX)
if INSTALL_MOBILE_STATIC
prereqs: $(PREREQSI_IL_AOT) $(PREREQSI_CS_AOT) $(AOT_EXTRA_LIBS)
@$(MCS) -r:TestDriver.dll $(srcdir)/debug-casts.cs
@$(RUNTIME) --debug=casts debug-casts.exe
-EXTRA_DIST += sgen-bridge.cs sgen-descriptors.cs sgen-gshared-vtype.cs sgen-bridge-major-fragmentation.cs sgen-domain-unload.cs sgen-weakref-stress.cs sgen-cementing-stress.cs sgen-case-23400.cs finalizer-wait.cs critical-finalizers.cs sgen-domain-unload-2.cs sgen-suspend.cs sgen-new-threads-dont-join-stw.cs sgen-new-threads-dont-join-stw-2.cs sgen-bridge-xref.cs bug-17590.cs sgen-toggleref.cs sgen-bridge-gchandle.cs
+EXTRA_DIST += sgen-bridge.cs sgen-descriptors.cs sgen-gshared-vtype.cs sgen-bridge-major-fragmentation.cs sgen-domain-unload.cs sgen-weakref-stress.cs sgen-cementing-stress.cs sgen-case-23400.cs finalizer-wait.cs critical-finalizers.cs sgen-domain-unload-2.cs sgen-suspend.cs sgen-new-threads-dont-join-stw.cs sgen-new-threads-dont-join-stw-2.cs sgen-new-threads-collect.cs sgen-bridge-xref.cs bug-17590.cs sgen-toggleref.cs sgen-bridge-gchandle.cs
sgen-tests:
sgen-case-23400.exe \
sgen-new-threads-dont-join-stw.exe \
sgen-new-threads-dont-join-stw-2.exe \
+ sgen-new-threads-collect.exe \
gc-graystack-stress.exe \
bug-17590.exe
--- /dev/null
+
+using System;
+using System.Linq;
+using System.Threading;
+
+class Driver
+{
+ class ThreadPoolLauncherObject
+ {
+ public volatile int i = 0;
+
+ public ThreadPoolLauncherObject ()
+ {
+ ThreadPool.QueueUserWorkItem (_ => { for (int i = 0; i < 10 * 1000 * 1000; ++i); }, null);
+ }
+ }
+
+ public static void Main ()
+ {
+ int count = 0;
+ object o = new object ();
+
+ foreach (var i in
+ Enumerable.Range (0, 100)
+ .AsParallel ().WithDegreeOfParallelism (Environment.ProcessorCount)
+ .Select (i => {
+ AppDomain ad;
+
+ ad = AppDomain.CreateDomain ("testdomain" + i);
+ ad.CreateInstance (typeof (ThreadPoolLauncherObject).Assembly.FullName, typeof (ThreadPoolLauncherObject).FullName);
+
+ Thread.Sleep (10);
+
+ AppDomain.Unload (ad);
+
+ return i;
+ })
+ .Select (i => {
+ lock (o) {
+ count += 1;
+
+ Console.Write (".");
+ if (count % 25 == 0)
+ Console.WriteLine ();
+ }
+
+ return i;
+ })
+ ) {
+ }
+ }
+}
using System;
using System.Reflection;
+// this for test_0_missing_attr_on_assembly
+[assembly: MissingAttribute]
+
public sealed class MyAttribute : Attribute
{
public Type Type { get; set; }
class Tests {
+ public static int test_0_missing_attr_on_assembly () {
+ try {
+ Assembly.GetExecutingAssembly().GetCustomAttributes (false);
+ return 1;
+ } catch (TypeLoadException exn) {
+ return 0;
+ }
+ }
+
[My3 (new object[] { DisappearingEnum.V0 })]
public static int test_0_missing_enum_arg_alt3 () {
try {
--- /dev/null
+
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+
+class Driver
+{
+ public static void Main ()
+ {
+ BlockingCollection<Thread> threads = new BlockingCollection<Thread> (new ConcurrentQueue<Thread> (), 128);
+
+ bool finished = false;
+
+ Thread gcThread = new Thread (() => {
+ while (!finished) {
+ GC.Collect ();
+ Thread.Yield ();
+ }
+ });
+
+ Thread joinThread = new Thread (() => {
+ for (int i = 0; ; ++i) {
+ Thread t = threads.Take ();
+ if (t == null)
+ break;
+ t.Join ();
+ if ((i + 1) % (50) == 0)
+ Console.Write (".");
+ if ((i + 1) % (50 * 50) == 0)
+ Console.WriteLine ();
+ }
+ });
+
+ gcThread.Start ();
+ joinThread.Start ();
+
+ for (int i = 0; i < 10 * 1000; ++i) {
+ Thread t = new Thread (() => { Thread.Yield (); });
+ t.Start ();
+
+ threads.Add (t);
+ }
+
+ threads.Add (null);
+
+ joinThread.Join ();
+
+ finished = true;
+ gcThread.Join ();
+ }
+}
\ No newline at end of file
--- /dev/null
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+class Driver
+{
+ public static void Main ()
+ {
+ bool finished = false;
+
+ Thread t1 = new Thread (() => {
+ while (!finished) {}
+ });
+
+ Thread t2 = new Thread (() => {
+ while (!finished) {
+ GC.Collect ();
+ Thread.Yield ();
+ }
+ });
+
+ t1.Start ();
+ t2.Start ();
+
+ Thread.Sleep (10);
+
+ for (int i = 0; i < 50 * 40 * 20; ++i) {
+ t1.Suspend ();
+ Thread.Yield ();
+ t1.Resume ();
+ if ((i + 1) % (50) == 0)
+ Console.Write (".");
+ if ((i + 1) % (50 * 40) == 0)
+ Console.WriteLine ();
+ }
+
+ finished = true;
+
+ t1.Join ();
+ t2.Join ();
+ }
+}
#include "utils/mono-threads.h"
#include "utils/mono-conc-hashtable.h"
#include "utils/checked-build.h"
-#include "utils/w32handle.h"
+#include "metadata/w32handle.h"
#include <stdlib.h>
#include <string.h>
parse.h \
checked-build.c \
checked-build.h \
- w32handle.c \
- w32handle.h \
os-event.h
arch_sources =
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state;
+ x86_float_state64_t *arch_fpstate = (x86_float_state64_t *) fpstate;
struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
-
ctx->__ss = *arch_state;
+ ctx->__fs = *arch_fpstate;
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state;
+ x86_float_state64_t *arch_fpstate = (x86_float_state64_t *) fpstate;
struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
-
*arch_state = ctx->__ss;
+ *arch_fpstate = ctx->__fs;
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state;
+ x86_float_state64_t *arch_fpstate = (x86_float_state64_t *) fpstate;
context->gregs [AMD64_RAX] = arch_state->__rax;
context->gregs [AMD64_RBX] = arch_state->__rbx;
context->gregs [AMD64_RCX] = arch_state->__rcx;
context->gregs [AMD64_R14] = arch_state->__r14;
context->gregs [AMD64_R15] = arch_state->__r15;
context->gregs [AMD64_RIP] = arch_state->__rip;
+ context->fregs [AMD64_XMM0] = arch_fpstate->__fpu_xmm0;
+ context->fregs [AMD64_XMM1] = arch_fpstate->__fpu_xmm1;
+ context->fregs [AMD64_XMM2] = arch_fpstate->__fpu_xmm2;
+ context->fregs [AMD64_XMM3] = arch_fpstate->__fpu_xmm3;
+ context->fregs [AMD64_XMM4] = arch_fpstate->__fpu_xmm4;
+ context->fregs [AMD64_XMM5] = arch_fpstate->__fpu_xmm5;
+ context->fregs [AMD64_XMM6] = arch_fpstate->__fpu_xmm6;
+ context->fregs [AMD64_XMM7] = arch_fpstate->__fpu_xmm7;
+ context->fregs [AMD64_XMM8] = arch_fpstate->__fpu_xmm8;
+ context->fregs [AMD64_XMM9] = arch_fpstate->__fpu_xmm9;
+ context->fregs [AMD64_XMM10] = arch_fpstate->__fpu_xmm10;
+ context->fregs [AMD64_XMM11] = arch_fpstate->__fpu_xmm11;
+ context->fregs [AMD64_XMM12] = arch_fpstate->__fpu_xmm12;
+ context->fregs [AMD64_XMM13] = arch_fpstate->__fpu_xmm13;
+ context->fregs [AMD64_XMM14] = arch_fpstate->__fpu_xmm14;
+ context->fregs [AMD64_XMM15] = arch_fpstate->__fpu_xmm15;
}
int
return sizeof (x86_thread_state64_t);
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ return sizeof (x86_float_state64_t);
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
- x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state;
+ x86_thread_state64_t *arch_state = (x86_thread_state64_t *)state;
+ x86_float_state64_t *arch_fpstate = (x86_float_state64_t *)fpstate;
kern_return_t ret;
*count = x86_THREAD_STATE64_COUNT;
+ *fpcount = x86_FLOAT_STATE64_COUNT;
- ret = thread_get_state (thread, x86_THREAD_STATE64, (thread_state_t) arch_state, count);
+ ret = thread_get_state (thread, x86_THREAD_STATE64, (thread_state_t)arch_state, count);
+ if (ret != KERN_SUCCESS)
+ return ret;
+ ret = thread_get_state (thread, x86_FLOAT_STATE64, (thread_state_t)arch_fpstate, fpcount);
return ret;
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
- return thread_set_state (thread, x86_THREAD_STATE64, state, count);
+ kern_return_t ret;
+ ret = thread_set_state (thread, x86_THREAD_STATE64, state, count);
+ if (ret != KERN_SUCCESS)
+ return ret;
+ ret = thread_set_state (thread, x86_FLOAT_STATE64, fpstate, fpcount);
+ return ret;
}
void *
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
int i;
arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
return sizeof (arm_thread_state_t);
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ g_assert_not_reached ();
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
#if defined(HOST_WATCHOS)
g_error ("thread_get_state() is not supported by this platform");
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
#if defined(HOST_WATCHOS)
g_error ("thread_set_state() is not supported by this platform");
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
int i;
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
return sizeof (arm_unified_thread_state_t);
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ g_assert_not_reached ();
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
kern_return_t ret;
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE, state, count);
}
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
g_assert_not_reached ();
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
g_assert_not_reached ();
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
g_assert_not_reached ();
}
g_assert_not_reached ();
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ g_assert_not_reached ();
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
g_assert_not_reached ();
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
g_assert_not_reached ();
}
#include "utils/mono-sigcontext.h"
#include "mach-support.h"
+// For reg numbers
+#include <mono/arch/amd64/amd64-codegen.h>
+
/* Known offsets used for TLS storage*/
/* All OSX versions up to 10.8 */
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state;
+ x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate;
struct __darwin_mcontext32 *ctx = (struct __darwin_mcontext32 *) context;
-
ctx->__ss = *arch_state;
+ ctx->__fs = *arch_fpstate;
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state;
+ x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate;
struct __darwin_mcontext32 *ctx = (struct __darwin_mcontext32 *) context;
-
*arch_state = ctx->__ss;
+ *arch_fpstate = ctx->__fs;
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state;
+ x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) state;
context->eax = arch_state->__eax;
context->ebx = arch_state->__ebx;
context->ecx = arch_state->__ecx;
context->esi = arch_state->__edi;
context->edi = arch_state->__esi;
context->eip = arch_state->__eip;
+ context->fregs [X86_XMM0] = arch_fpstate->__fpu_xmm0;
+ context->fregs [X86_XMM1] = arch_fpstate->__fpu_xmm1;
+ context->fregs [X86_XMM2] = arch_fpstate->__fpu_xmm2;
+ context->fregs [X86_XMM3] = arch_fpstate->__fpu_xmm3;
+ context->fregs [X86_XMM4] = arch_fpstate->__fpu_xmm4;
+ context->fregs [X86_XMM5] = arch_fpstate->__fpu_xmm5;
+ context->fregs [X86_XMM6] = arch_fpstate->__fpu_xmm6;
+ context->fregs [X86_XMM7] = arch_fpstate->__fpu_xmm7;
}
-
int
mono_mach_arch_get_thread_state_size ()
{
return sizeof (x86_thread_state32_t);
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ return sizeof (x86_float_state32_t);
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
#if defined(HOST_WATCHOS)
g_error ("thread_get_state() is not supported by this platform");
#else
x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state;
+ x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate;
kern_return_t ret;
*count = x86_THREAD_STATE32_COUNT;
- ret = thread_get_state (thread, x86_THREAD_STATE32, (thread_state_t) arch_state, count);
+ *fpcount = x86_FLOAT_STATE32_COUNT;
+
+ ret = thread_get_state (thread, x86_THREAD_STATE32, (thread_state_t)arch_state, count);
+ if (ret != KERN_SUCCESS)
+ return ret;
+ ret = thread_get_state (thread, x86_FLOAT_STATE32, (thread_state_t)arch_fpstate, fpcount);
return ret;
#endif
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
#if defined(HOST_WATCHOS)
g_error ("thread_set_state() is not supported by this platform");
#else
- return thread_set_state (thread, x86_THREAD_STATE32, state, count);
+ kern_return_t ret;
+ ret = thread_set_state (thread, x86_THREAD_STATE32, state, count);
+ if (ret != KERN_SUCCESS)
+ return ret;
+ ret = thread_set_state (thread, x86_FLOAT_STATE32, fpstate, fpcount);
+ return ret;
#endif
}
void mono_mach_init (pthread_key_t key);
int mono_mach_arch_get_mcontext_size (void);
-void mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context);
-void mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state);
-void mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context);
+void mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context);
+void mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate);
+void mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context);
+/* FIXME: Should return size_t, not int. */
int mono_mach_arch_get_thread_state_size (void);
+int mono_mach_arch_get_thread_fpstate_size (void);
kern_return_t mono_mach_get_threads (thread_act_array_t *threads, guint32 *count);
kern_return_t mono_mach_free_threads (thread_act_array_t threads, guint32 count);
-kern_return_t mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count);
-kern_return_t mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count);
+kern_return_t mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount);
+kern_return_t mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount);
void *mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key);
void *mono_mach_get_tls_address_from_thread (pthread_t thread, pthread_key_t key);
{
int minsize, flags = CODE_FLAG_MMAP;
int chunk_size, bsize = 0;
- int pagesize;
+ int pagesize, valloc_granule;
CodeChunk *chunk;
void *ptr;
#endif
pagesize = mono_pagesize ();
+ valloc_granule = mono_valloc_granule ();
if (dynamic) {
chunk_size = size;
flags = CODE_FLAG_MALLOC;
} else {
- minsize = pagesize * MIN_PAGES;
+ minsize = MAX (pagesize * MIN_PAGES, valloc_granule);
if (size < minsize)
chunk_size = minsize;
else {
size += MIN_ALIGN - 1;
size &= ~(MIN_ALIGN - 1);
chunk_size = size;
- chunk_size += pagesize - 1;
- chunk_size &= ~ (pagesize - 1);
+ chunk_size += valloc_granule - 1;
+ chunk_size &= ~ (valloc_granule - 1);
}
}
#ifdef BIND_ROOM
if (chunk_size - size < bsize) {
chunk_size = size + bsize;
if (!dynamic) {
- chunk_size += pagesize - 1;
- chunk_size &= ~ (pagesize - 1);
+ chunk_size += valloc_granule - 1;
+ chunk_size &= ~ (valloc_granule - 1);
}
}
#endif
mctx->gregs [AMD64_R14] = UCONTEXT_REG_R14 (ctx);
mctx->gregs [AMD64_R15] = UCONTEXT_REG_R15 (ctx);
mctx->gregs [AMD64_RIP] = UCONTEXT_REG_RIP (ctx);
+
+#ifdef UCONTEXT_REG_XMM
+ mctx->fregs [0] = UCONTEXT_REG_XMM0 (ctx);
+ mctx->fregs [1] = UCONTEXT_REG_XMM1 (ctx);
+ mctx->fregs [2] = UCONTEXT_REG_XMM2 (ctx);
+ mctx->fregs [3] = UCONTEXT_REG_XMM3 (ctx);
+ mctx->fregs [4] = UCONTEXT_REG_XMM4 (ctx);
+ mctx->fregs [5] = UCONTEXT_REG_XMM5 (ctx);
+ mctx->fregs [6] = UCONTEXT_REG_XMM6 (ctx);
+ mctx->fregs [7] = UCONTEXT_REG_XMM7 (ctx);
+ mctx->fregs [8] = UCONTEXT_REG_XMM8 (ctx);
+ mctx->fregs [9] = UCONTEXT_REG_XMM9 (ctx);
+ mctx->fregs [10] = UCONTEXT_REG_XMM10 (ctx);
+ mctx->fregs [11] = UCONTEXT_REG_XMM11 (ctx);
+ mctx->fregs [12] = UCONTEXT_REG_XMM12 (ctx);
+ mctx->fregs [13] = UCONTEXT_REG_XMM13 (ctx);
+ mctx->fregs [14] = UCONTEXT_REG_XMM14 (ctx);
+ mctx->fregs [15] = UCONTEXT_REG_XMM15 (ctx);
+#endif
+
#elif defined(HOST_WIN32)
CONTEXT *context = (CONTEXT*)sigctx;
UCONTEXT_REG_R14 (ctx) = mctx->gregs [AMD64_R14];
UCONTEXT_REG_R15 (ctx) = mctx->gregs [AMD64_R15];
UCONTEXT_REG_RIP (ctx) = mctx->gregs [AMD64_RIP];
+
+#ifdef UCONTEXT_REG_XMM
+ UCONTEXT_REG_XMM0 (ctx) = mctx->fregs [0];
+ UCONTEXT_REG_XMM1 (ctx) = mctx->fregs [1];
+ UCONTEXT_REG_XMM2 (ctx) = mctx->fregs [2];
+ UCONTEXT_REG_XMM3 (ctx) = mctx->fregs [3];
+ UCONTEXT_REG_XMM4 (ctx) = mctx->fregs [4];
+ UCONTEXT_REG_XMM5 (ctx) = mctx->fregs [5];
+ UCONTEXT_REG_XMM6 (ctx) = mctx->fregs [6];
+ UCONTEXT_REG_XMM7 (ctx) = mctx->fregs [7];
+ UCONTEXT_REG_XMM8 (ctx) = mctx->fregs [8];
+ UCONTEXT_REG_XMM9 (ctx) = mctx->fregs [9];
+ UCONTEXT_REG_XMM10 (ctx) = mctx->fregs [10];
+ UCONTEXT_REG_XMM11 (ctx) = mctx->fregs [11];
+ UCONTEXT_REG_XMM12 (ctx) = mctx->fregs [12];
+ UCONTEXT_REG_XMM13 (ctx) = mctx->fregs [13];
+ UCONTEXT_REG_XMM14 (ctx) = mctx->fregs [14];
+ UCONTEXT_REG_XMM15 (ctx) = mctx->fregs [15];
+#endif
+
#elif defined(HOST_WIN32)
CONTEXT *context = (CONTEXT*)sigctx;
#include <signal.h>
#endif
+#define MONO_CONTEXT_OFFSET(field, index, field_type) \
+ "i" (offsetof (MonoContext, field) + (index) * sizeof (field_type))
+
+#if defined(__APPLE__)
+typedef struct __darwin_xmm_reg MonoContextSimdReg;
+#endif
+
/*
* General notes about mono-context.
* Each arch defines a MonoContext struct with all GPR regs + IP/PC.
# define SC_ESI esi
#endif
+#include <mono/arch/x86/x86-codegen.h>
+
typedef struct {
mgreg_t eax;
mgreg_t ebx;
mgreg_t esi;
mgreg_t edi;
mgreg_t eip;
+#ifdef __APPLE__
+ MonoContextSimdReg fregs [X86_XMM_NREG];
+#endif
} MonoContext;
#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->eip = (mgreg_t)(ip); } while (0);
#else
#define MONO_CONTEXT_GET_CURRENT(ctx) \
__asm__ __volatile__( \
- "movl $0x0, 0x00(%0)\n" \
- "mov %%ebx, 0x04(%0)\n" \
- "mov %%ecx, 0x08(%0)\n" \
- "mov %%edx, 0x0c(%0)\n" \
- "mov %%ebp, 0x10(%0)\n" \
- "mov %%esp, 0x14(%0)\n" \
- "mov %%esi, 0x18(%0)\n" \
- "mov %%edi, 0x1c(%0)\n" \
+ "movl $0x0, %c[eax](%0)\n" \
+ "mov %%ebx, %c[ebx](%0)\n" \
+ "mov %%ecx, %c[ecx](%0)\n" \
+ "mov %%edx, %c[edx](%0)\n" \
+ "mov %%ebp, %c[ebp](%0)\n" \
+ "mov %%esp, %c[esp](%0)\n" \
+ "mov %%esi, %c[esi](%0)\n" \
+ "mov %%edi, %c[edi](%0)\n" \
"call 1f\n" \
"1: pop 0x20(%0)\n" \
: \
- : "a" (&(ctx)) \
+ : "a" (&(ctx)), \
+ [eax] MONO_CONTEXT_OFFSET (eax, 0, mgreg_t), \
+ [ebx] MONO_CONTEXT_OFFSET (ebx, 0, mgreg_t), \
+ [ecx] MONO_CONTEXT_OFFSET (ecx, 0, mgreg_t), \
+ [edx] MONO_CONTEXT_OFFSET (edx, 0, mgreg_t), \
+ [ebp] MONO_CONTEXT_OFFSET (ebp, 0, mgreg_t), \
+ [esp] MONO_CONTEXT_OFFSET (esp, 0, mgreg_t), \
+ [esi] MONO_CONTEXT_OFFSET (esi, 0, mgreg_t), \
+ [edi] MONO_CONTEXT_OFFSET (edi, 0, mgreg_t) \
: "memory")
#endif
typedef struct {
mgreg_t gregs [AMD64_NREG];
+#ifdef __APPLE__
+ MonoContextSimdReg fregs [AMD64_XMM_NREG];
+#else
double fregs [AMD64_XMM_NREG];
+#endif
} MonoContext;
#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->gregs [AMD64_RIP] = (mgreg_t)(ip); } while (0);
: "rdx", "memory")
#else
-#define MONO_CONTEXT_GET_CURRENT(ctx) \
- __asm__ __volatile__( \
- "movq $0x0, 0x00(%0)\n" \
- "movq %%rcx, 0x08(%0)\n" \
- "movq %%rdx, 0x10(%0)\n" \
- "movq %%rbx, 0x18(%0)\n" \
- "movq %%rsp, 0x20(%0)\n" \
- "movq %%rbp, 0x28(%0)\n" \
- "movq %%rsi, 0x30(%0)\n" \
- "movq %%rdi, 0x38(%0)\n" \
- "movq %%r8, 0x40(%0)\n" \
- "movq %%r9, 0x48(%0)\n" \
- "movq %%r10, 0x50(%0)\n" \
- "movq %%r11, 0x58(%0)\n" \
- "movq %%r12, 0x60(%0)\n" \
- "movq %%r13, 0x68(%0)\n" \
- "movq %%r14, 0x70(%0)\n" \
- "movq %%r15, 0x78(%0)\n" \
- /* "leaq (%%rip), %%rdx\n" is not understood by icc */ \
- ".byte 0x48, 0x8d, 0x15, 0x00, 0x00, 0x00, 0x00\n" \
- "movq %%rdx, 0x80(%0)\n" \
- : \
- : "a" (&(ctx)) \
- : "rdx", "memory")
+#define MONO_CONTEXT_GET_CURRENT_GREGS(ctx) \
+ do { \
+ __asm__ __volatile__( \
+ "movq $0x0, %c[rax](%0)\n" \
+ "movq %%rcx, %c[rcx](%0)\n" \
+ "movq %%rdx, %c[rdx](%0)\n" \
+ "movq %%rbx, %c[rbx](%0)\n" \
+ "movq %%rsp, %c[rsp](%0)\n" \
+ "movq %%rbp, %c[rbp](%0)\n" \
+ "movq %%rsi, %c[rsi](%0)\n" \
+ "movq %%rdi, %c[rdi](%0)\n" \
+ "movq %%r8, %c[r8](%0)\n" \
+ "movq %%r9, %c[r9](%0)\n" \
+ "movq %%r10, %c[r10](%0)\n" \
+ "movq %%r11, %c[r11](%0)\n" \
+ "movq %%r12, %c[r12](%0)\n" \
+ "movq %%r13, %c[r13](%0)\n" \
+ "movq %%r14, %c[r14](%0)\n" \
+ "movq %%r15, %c[r15](%0)\n" \
+ /* "leaq (%%rip), %%rdx\n" is not understood by icc */ \
+ ".byte 0x48, 0x8d, 0x15, 0x00, 0x00, 0x00, 0x00\n" \
+ "movq %%rdx, %c[rip](%0)\n" \
+ : \
+ : "a" (&(ctx)), \
+ [rax] MONO_CONTEXT_OFFSET (gregs, AMD64_RAX, mgreg_t), \
+ [rcx] MONO_CONTEXT_OFFSET (gregs, AMD64_RCX, mgreg_t), \
+ [rdx] MONO_CONTEXT_OFFSET (gregs, AMD64_RDX, mgreg_t), \
+ [rbx] MONO_CONTEXT_OFFSET (gregs, AMD64_RBX, mgreg_t), \
+ [rsp] MONO_CONTEXT_OFFSET (gregs, AMD64_RSP, mgreg_t), \
+ [rbp] MONO_CONTEXT_OFFSET (gregs, AMD64_RBP, mgreg_t), \
+ [rsi] MONO_CONTEXT_OFFSET (gregs, AMD64_RSI, mgreg_t), \
+ [rdi] MONO_CONTEXT_OFFSET (gregs, AMD64_RDI, mgreg_t), \
+ [r8] MONO_CONTEXT_OFFSET (gregs, AMD64_R8, mgreg_t), \
+ [r9] MONO_CONTEXT_OFFSET (gregs, AMD64_R9, mgreg_t), \
+ [r10] MONO_CONTEXT_OFFSET (gregs, AMD64_R10, mgreg_t), \
+ [r11] MONO_CONTEXT_OFFSET (gregs, AMD64_R11, mgreg_t), \
+ [r12] MONO_CONTEXT_OFFSET (gregs, AMD64_R12, mgreg_t), \
+ [r13] MONO_CONTEXT_OFFSET (gregs, AMD64_R13, mgreg_t), \
+ [r14] MONO_CONTEXT_OFFSET (gregs, AMD64_R14, mgreg_t), \
+ [r15] MONO_CONTEXT_OFFSET (gregs, AMD64_R15, mgreg_t), \
+ [rip] MONO_CONTEXT_OFFSET (gregs, AMD64_RIP, mgreg_t) \
+ : "rdx", "memory"); \
+ } while (0)
+
+#ifdef UCONTEXT_REG_XMM
+#define MONO_CONTEXT_GET_CURRENT_FREGS(ctx) \
+ do { \
+ __asm__ __volatile__ ( \
+ "movups %%xmm0, %c[xmm0](%0)\n" \
+ "movups %%xmm1, %c[xmm1](%0)\n" \
+ "movups %%xmm2, %c[xmm2](%0)\n" \
+ "movups %%xmm3, %c[xmm3](%0)\n" \
+ "movups %%xmm4, %c[xmm4](%0)\n" \
+ "movups %%xmm5, %c[xmm5](%0)\n" \
+ "movups %%xmm6, %c[xmm6](%0)\n" \
+ "movups %%xmm7, %c[xmm7](%0)\n" \
+ "movups %%xmm8, %c[xmm8](%0)\n" \
+ "movups %%xmm9, %c[xmm9](%0)\n" \
+ "movups %%xmm10, %c[xmm10](%0)\n" \
+ "movups %%xmm11, %c[xmm11](%0)\n" \
+ "movups %%xmm12, %c[xmm12](%0)\n" \
+ "movups %%xmm12, %c[xmm12](%0)\n" \
+ "movups %%xmm14, %c[xmm14](%0)\n" \
+ "movups %%xmm15, %c[xmm15](%0)\n" \
+ : \
+ : "a" (&(ctx)), \
+ [xmm0] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM0, MonoContextSimdReg), \
+ [xmm1] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM1, MonoContextSimdReg), \
+ [xmm2] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM2, MonoContextSimdReg), \
+ [xmm3] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM3, MonoContextSimdReg), \
+ [xmm4] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM4, MonoContextSimdReg), \
+ [xmm5] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM5, MonoContextSimdReg), \
+ [xmm6] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM6, MonoContextSimdReg), \
+ [xmm7] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM7, MonoContextSimdReg), \
+ [xmm8] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM8, MonoContextSimdReg), \
+ [xmm9] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM9, MonoContextSimdReg), \
+ [xmm10] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM10, MonoContextSimdReg), \
+ [xmm11] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM11, MonoContextSimdReg), \
+ [xmm12] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM12, MonoContextSimdReg), \
+ [xmm13] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM13, MonoContextSimdReg), \
+ [xmm14] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM14, MonoContextSimdReg), \
+ [xmm15] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM15, MonoContextSimdReg)); \
+ } while (0)
+#else
+#define MONO_CONTEXT_GET_CURRENT_FREGS(ctx)
+#endif
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) \
+ do { \
+ MONO_CONTEXT_GET_CURRENT_GREGS(ctx); \
+ MONO_CONTEXT_GET_CURRENT_FREGS(ctx); \
+ } while (0)
#endif
#define MONO_ARCH_HAS_MONO_CONTEXT 1
"push {r0}\n" \
"push {r1}\n" \
"mov r0, %0\n" \
- "ldr r1, [sp, #4]\n" \
- "str r1, [r0]!\n" \
- "ldr r1, [sp, #0]\n" \
- "str r1, [r0]!\n" \
+ "ldr r1, [sp, #4]\n" \
+ "str r1, [r0], #4\n" \
+ "ldr r1, [sp, #0]\n" \
+ "str r1, [r0], #4\n" \
"stmia r0!, {r2-r12}\n" \
- "str sp, [r0]!\n" \
- "str lr, [r0]!\n" \
+ "str sp, [r0], #4\n" \
+ "str lr, [r0], #4\n" \
"mov r1, pc\n" \
- "str r1, [r0]!\n" \
+ "str r1, [r0], #4\n" \
"pop {r1}\n" \
"pop {r0}\n" \
: \
mgreg_t regs [32];
double fregs [32];
mgreg_t pc;
+ /*
+ * fregs might not be initialized if this context was created from a
+ * ucontext.
+ */
+ mgreg_t has_fregs;
} MonoContext;
#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->pc = (mgreg_t)ip; } while (0)
thread_port_t self = mach_thread_self (); \
kern_return_t ret = thread_get_state (self, state_flavor, (thread_state_t) &thread_state, &state_count); \
g_assert (ret == 0); \
- mono_mach_arch_thread_state_to_mono_context ((thread_state_t)&thread_state, &ctx); \
+ mono_mach_arch_thread_states_to_mono_context ((thread_state_t)&thread_state, (thread_state_t)NULL, &ctx); \
mach_port_deallocate (current_task (), self); \
} while (0);
if (saved_pagesize)
return saved_pagesize;
GetSystemInfo (&info);
- saved_pagesize = info.dwAllocationGranularity;
+ saved_pagesize = info.dwPageSize;
return saved_pagesize;
}
+int
+mono_valloc_granule (void)
+{
+ SYSTEM_INFO info;
+ static int saved_valloc_granule = 0;
+ if (saved_valloc_granule)
+ return saved_valloc_granule;
+ GetSystemInfo (&info);
+ saved_valloc_granule = info.dwAllocationGranularity;
+ return saved_valloc_granule;
+}
+
int
mono_mmap_win_prot_from_flags (int flags)
{
return saved_pagesize;
}
+int
+mono_valloc_granule (void)
+{
+ return mono_pagesize ();
+}
+
static int
prot_from_flags (int flags)
{
return 4096;
}
+int
+mono_valloc_granule (void)
+{
+ return mono_pagesize ();
+}
+
void*
mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
{
MONO_API int mono_file_map_close (MonoFileMap *fmap);
MONO_API int mono_pagesize (void);
+MONO_API int mono_valloc_granule (void);
MONO_API void* mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type);
MONO_API void* mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountType type);
MONO_API int mono_vfree (void *addr, size_t length, MonoMemAccountType type);
#define UCONTEXT_REG_R13(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r13)
#define UCONTEXT_REG_R14(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r14)
#define UCONTEXT_REG_R15(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r15)
+ #define UCONTEXT_REG_XMM
+ #define UCONTEXT_REG_XMM0(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm0)
+ #define UCONTEXT_REG_XMM1(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm1)
+ #define UCONTEXT_REG_XMM2(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm2)
+ #define UCONTEXT_REG_XMM3(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm3)
+ #define UCONTEXT_REG_XMM4(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm4)
+ #define UCONTEXT_REG_XMM5(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm5)
+ #define UCONTEXT_REG_XMM6(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm6)
+ #define UCONTEXT_REG_XMM7(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm7)
+ #define UCONTEXT_REG_XMM8(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm8)
+ #define UCONTEXT_REG_XMM9(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm9)
+ #define UCONTEXT_REG_XMM10(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm10)
+ #define UCONTEXT_REG_XMM11(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm11)
+ #define UCONTEXT_REG_XMM12(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm12)
+ #define UCONTEXT_REG_XMM13(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm13)
+ #define UCONTEXT_REG_XMM14(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm14)
+ #define UCONTEXT_REG_XMM15(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm15)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#define UCONTEXT_REG_RAX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rax)
#define UCONTEXT_REG_RBX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rbx)
#define UCONTEXT_REG_R14(ctx) (((ucontext_t*)(ctx))->sc_r14)
#define UCONTEXT_REG_R15(ctx) (((ucontext_t*)(ctx))->sc_r15)
#elif !defined(HOST_WIN32)
-#define UCONTEXT_GREGS(ctx) ((guint64*)&(((ucontext_t*)(ctx))->uc_mcontext.gregs))
+ #define UCONTEXT_GREGS(ctx) ((guint64*)&(((ucontext_t*)(ctx))->uc_mcontext.gregs))
#endif
#ifdef UCONTEXT_GREGS
/* commit the saved state and notify others if needed */
switch (mono_threads_transition_state_poll (info)) {
case SelfSuspendResumed:
- return;
+ break;
case SelfSuspendWait:
mono_thread_info_wait_for_resume (info);
break;
mono_thread_info_wait_for_resume (info);
break;
}
+
+ if (info->async_target) {
+ info->async_target (info->user_data);
+ info->async_target = NULL;
+ info->user_data = NULL;
+ }
}
static volatile gpointer* dummy_global;
if (info->async_target) {
MonoContext tmp = info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx;
- mach_msg_type_number_t num_state;
- thread_state_t state;
+ mach_msg_type_number_t num_state, num_fpstate;
+ thread_state_t state, fpstate;
ucontext_t uctx;
mcontext_t mctx;
info->async_target = (void (*)(void *)) info->user_data;
state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ());
+ fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ());
mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ());
do {
- ret = mono_mach_arch_get_thread_state (info->native_handle, state, &num_state);
+ ret = mono_mach_arch_get_thread_states (info->native_handle, state, &num_state, fpstate, &num_fpstate);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
return FALSE;
- mono_mach_arch_thread_state_to_mcontext (state, mctx);
+ mono_mach_arch_thread_states_to_mcontext (state, fpstate, mctx);
uctx.uc_mcontext = mctx;
mono_monoctx_to_sigctx (&tmp, &uctx);
- mono_mach_arch_mcontext_to_thread_state (mctx, state);
+ mono_mach_arch_mcontext_to_thread_states (mctx, state, fpstate);
do {
- ret = mono_mach_arch_set_thread_state (info->native_handle, state, num_state);
+ ret = mono_mach_arch_set_thread_states (info->native_handle, state, num_state, fpstate, num_fpstate);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-coop-semaphore.h>
#include <mono/metadata/gc-internals.h>
-#include <mono/utils/w32handle.h>
#include <mono/utils/mono-threads-debug.h>
#include <errno.h>
#include <sys/resource.h>
-#if defined(__native_client__)
-void nacl_shutdown_gc_thread(void);
-#endif
-
-void
-mono_threads_platform_register (MonoThreadInfo *info)
-{
- gpointer thread_handle;
-
- thread_handle = mono_w32handle_new (MONO_W32HANDLE_THREAD, NULL);
- if (thread_handle == INVALID_HANDLE_VALUE)
- g_error ("%s: failed to create handle", __func__);
-
- g_assert (!info->handle);
- info->handle = thread_handle;
-}
-
int
mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid)
{
}
void
-mono_threads_platform_exit (int exit_code)
+mono_threads_platform_exit (gsize exit_code)
{
-#if defined(__native_client__)
- nacl_shutdown_gc_thread();
-#endif
-
- mono_thread_info_detach ();
-
- pthread_exit (NULL);
-}
-
-void
-mono_threads_platform_unregister (MonoThreadInfo *info)
-{
- g_assert (info->handle);
-
- /* The thread is no longer active, so unref it */
- mono_w32handle_unref (info->handle);
- info->handle = NULL;
+ pthread_exit ((gpointer) exit_code);
}
int
return (int)lim.rlim_max;
}
-gpointer
-mono_threads_platform_duplicate_handle (MonoThreadInfo *info)
-{
- g_assert (info->handle);
- mono_w32handle_ref (info->handle);
- return info->handle;
-}
-
-HANDLE
-mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
-{
- mono_w32handle_ref (handle);
-
- return handle;
-}
-
-void
-mono_threads_platform_close_thread_handle (HANDLE handle)
-{
- mono_w32handle_unref (handle);
-}
-
int
mono_threads_pthread_kill (MonoThreadInfo *info, int signum)
{
return !pthread_join (tid, &res);
}
-void
-mono_threads_platform_set_exited (gpointer handle)
-{
- int thr_ret;
-
- g_assert (handle);
- if (mono_w32handle_issignalled (handle))
- g_error ("%s: handle %p thread %p has already exited, it's handle is signalled", __func__, handle, mono_native_thread_id_get ());
- if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_UNUSED)
- g_error ("%s: handle %p thread %p has already exited, it's handle type is 'unused'", __func__, handle, mono_native_thread_id_get ());
-
- thr_ret = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-}
-
-static const gchar* thread_typename (void)
-{
- return "Thread";
-}
-
-static gsize thread_typesize (void)
-{
- return 0;
-}
-
-static MonoW32HandleOps thread_ops = {
- NULL, /* close */
- NULL, /* signal */
- NULL, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- NULL, /* details */
- thread_typename, /* typename */
- thread_typesize, /* typesize */
-};
-
-void
-mono_threads_platform_init (void)
-{
- mono_w32handle_register_ops (MONO_W32HANDLE_THREAD, &thread_ops);
-
- mono_w32handle_register_capabilities (MONO_W32HANDLE_THREAD, MONO_W32HANDLE_CAP_WAIT);
-}
-
#endif /* defined(_POSIX_VERSION) || defined(__native_client__) */
#if defined(USE_POSIX_BACKEND)
gboolean
mono_threads_suspend_begin_async_resume (MonoThreadInfo *info)
{
- mono_threads_add_to_pending_operation_set (info);
- return mono_threads_pthread_kill (info, mono_threads_suspend_get_restart_signal ()) == 0;
+ int sig = mono_threads_suspend_get_restart_signal ();
+
+ if (!mono_threads_pthread_kill (info, sig)) {
+ mono_threads_add_to_pending_operation_set (info);
+ return TRUE;
+ }
+ return FALSE;
}
void
#if defined (HOST_WIN32)
-void
-mono_threads_platform_register (MonoThreadInfo *info)
-{
- HANDLE thread_handle;
-
- thread_handle = GetCurrentThread ();
- g_assert (thread_handle);
-
- /* The handle returned by GetCurrentThread () is a pseudo handle, so it can't
- * be used to refer to the thread from other threads for things like aborting. */
- DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0);
-
- g_assert (!info->handle);
- info->handle = thread_handle;
-}
-
int
mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid)
{
}
void
-mono_threads_platform_exit (int exit_code)
+mono_threads_platform_exit (gsize exit_code)
{
- mono_thread_info_detach ();
ExitThread (exit_code);
}
-void
-mono_threads_platform_unregister (MonoThreadInfo *info)
-{
- g_assert (info->handle);
-
- CloseHandle (info->handle);
- info->handle = NULL;
-}
-
int
mono_threads_get_max_stack_size (void)
{
return INT_MAX;
}
-gpointer
-mono_threads_platform_duplicate_handle (MonoThreadInfo *info)
-{
- HANDLE thread_handle;
-
- g_assert (info->handle);
- DuplicateHandle (GetCurrentProcess (), info->handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0);
-
- return thread_handle;
-}
-
-HANDLE
-mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
-{
- return OpenThread (THREAD_ALL_ACCESS, TRUE, tid);
-}
-
-void
-mono_threads_platform_close_thread_handle (HANDLE handle)
-{
- CloseHandle (handle);
-}
-
#if defined(_MSC_VER)
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
#endif
}
-void
-mono_threads_platform_set_exited (gpointer handle)
-{
-}
-
-void
-mono_threads_platform_init (void)
-{
-}
-
#endif
#include <mono/utils/mono-coop-semaphore.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/mono-threads-debug.h>
+#include <mono/utils/os-event.h>
#include <errno.h>
mono_thread_info_set_tid (info, mono_native_thread_id_get ());
info->small_id = small_id;
+ info->handle = g_new0 (MonoThreadHandle, 1);
+ info->handle->ref = 1;
+ mono_os_event_init (&info->handle->event, TRUE, FALSE);
+
mono_os_sem_init (&info->resume_semaphore, 0);
/*set TLS early so SMR works */
info->stackdata = g_byte_array_new ();
- mono_threads_platform_register (info);
mono_threads_suspend_register (info);
/*
static void
mono_thread_info_suspend_lock_with_info (MonoThreadInfo *info);
+static void
+mono_threads_signal_thread_handle (MonoThreadHandle* thread_handle);
+
static void
unregister_thread (void *arg)
{
/* we need to duplicate it, as the info->handle is going
* to be closed when unregistering from the platform */
- handle = mono_threads_platform_duplicate_handle (info);
+ handle = mono_threads_open_thread_handle (info->handle);
/*
First perform the callback that requires no locks.
if (threads_callbacks.thread_unregister)
threads_callbacks.thread_unregister (info);
- mono_threads_platform_unregister (info);
+ /* The thread is no longer active, so unref its handle */
+ mono_threads_close_thread_handle (info->handle);
+ info->handle = NULL;
+
result = mono_thread_info_remove (info);
g_assert (result);
mono_threads_transition_detach (info);
mono_thread_small_id_free (small_id);
- /* Signal the w32handle. It can be done as late as here
- * because w32handle does not access the current MonoThreadInfo,
- * neither does it switch state to BLOCKING. */
- mono_threads_platform_set_exited (handle);
+ mono_threads_signal_thread_handle (handle);
- mono_threads_platform_close_thread_handle (handle);
+ mono_threads_close_thread_handle (handle);
}
static void
mono_lls_init (&thread_list, NULL);
mono_thread_smr_init ();
- mono_threads_platform_init ();
mono_threads_suspend_init ();
mono_threads_suspend_init_signals ();
mono_threads_coop_init ();
void
mono_thread_info_begin_self_suspend (void)
{
+ g_assert (!mono_threads_is_coop_enabled ());
+
MonoThreadInfo *info = mono_thread_info_current_unchecked ();
if (!info)
return;
{
MonoThreadInfo *info;
+ g_assert (!mono_threads_is_coop_enabled ());
+
info = mono_thread_info_current ();
if (!info)
return;
if (stack_start < info->stack_start_limit || stack_start >= info->stack_end)
return TRUE;
+ if (threads_callbacks.ip_in_critical_region)
+ return threads_callbacks.ip_in_critical_region ((MonoDomain *) state->unwind_data [MONO_UNWIND_DATA_DOMAIN], (char *) MONO_CONTEXT_GET_IP (&state->ctx));
+
ji = mono_jit_info_table_find (
(MonoDomain *) state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
(char *) MONO_CONTEXT_GET_IP (&state->ctx));
}
break;
case AsyncSuspendBlocking:
- if (interrupt_kernel)
+ if (interrupt_kernel && mono_threads_suspend_needs_abort_syscall ())
mono_threads_suspend_abort_syscall (info);
break;
mono_threads_wait_pending_operations ();
break;
case KeepSuspended:
+ g_assert (!mono_threads_is_coop_enabled ());
break;
default:
g_error ("Invalid suspend_and_run callback return value %d", result);
gpointer start_routine_arg;
gint32 priority;
MonoCoopSem registered;
- gpointer handle;
+ MonoThreadHandle *handle;
} CreateThreadData;
static gsize WINAPI
MonoThreadInfo *info;
MonoThreadStart start_routine;
gpointer start_routine_arg;
- guint32 start_routine_res;
+ gsize start_routine_res;
gsize dummy;
thread_data = (CreateThreadData*) data;
info = mono_thread_info_attach (&dummy);
info->runtime_thread = TRUE;
- thread_data->handle = mono_thread_info_duplicate_handle (info);
+ thread_data->handle = mono_threads_open_thread_handle (info->handle);
mono_coop_sem_post (&thread_data->registered);
/* Run the actual main function of the thread */
start_routine_res = start_routine (start_routine_arg);
- mono_threads_platform_exit (start_routine_res);
+ mono_thread_info_exit (start_routine_res);
g_assert_not_reached ();
}
* Create a new thread executing START with argument ARG. Store its id into OUT_TID.
* Returns: a windows or io-layer handle for the thread.
*/
-HANDLE
+MonoThreadHandle*
mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize * const stack_size, MonoNativeThreadId *out_tid)
{
CreateThreadData *thread_data;
gint res;
- gpointer ret;
+ MonoThreadHandle *ret;
thread_data = g_new0 (CreateThreadData, 1);
thread_data->ref = 2;
((MonoThreadInfo*)info)->tls [key] = value;
}
+#if defined(__native_client__)
+void nacl_shutdown_gc_thread(void);
+#endif
+
/*
* mono_thread_info_exit:
*
* This function doesn't return.
*/
void
-mono_thread_info_exit (void)
+mono_thread_info_exit (gsize exit_code)
{
+#if defined(__native_client__)
+ nacl_shutdown_gc_thread();
+#endif
+
+ mono_thread_info_detach ();
+
mono_threads_platform_exit (0);
}
/*
* mono_threads_open_thread_handle:
*
- * Return a io-layer/win32 handle for the thread identified by HANDLE/TID.
- * The handle need to be closed by calling CloseHandle () when it is no
- * longer needed.
+ * Duplicate the handle. The handle needs to be closed by calling
+ * mono_threads_close_thread_handle () when it is no longer needed.
*/
-HANDLE
-mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
+MonoThreadHandle*
+mono_threads_open_thread_handle (MonoThreadHandle *thread_handle)
{
- return mono_threads_platform_open_thread_handle (handle, tid);
+ guint32 oldref, newref;
+
+ g_assert (thread_handle);
+
+ do {
+ oldref = thread_handle->ref;
+ if (!(oldref >= 1))
+ g_error ("%s: thread_handle %p has ref %u, it should be >= 1", __func__, thread_handle, oldref);
+
+ newref = oldref + 1;
+ } while (InterlockedCompareExchange ((gint32*) &thread_handle->ref, newref, oldref) != oldref);
+
+ return thread_handle;
}
void
-mono_threads_close_thread_handle (HANDLE handle)
+mono_threads_close_thread_handle (MonoThreadHandle *thread_handle)
+{
+ guint32 oldref, newref;
+
+ g_assert (thread_handle);
+
+ do {
+ oldref = thread_handle->ref;
+ if (!(oldref >= 1))
+ g_error ("%s: thread_handle %p has ref %u, it should be >= 1", __func__, thread_handle, oldref);
+
+ newref = oldref - 1;
+ } while (InterlockedCompareExchange ((gint32*) &thread_handle->ref, newref, oldref) != oldref);
+
+ if (newref == 0) {
+ mono_os_event_destroy (&thread_handle->event);
+ g_free (thread_handle);
+ }
+}
+
+static void
+mono_threads_signal_thread_handle (MonoThreadHandle* thread_handle)
{
- return mono_threads_platform_close_thread_handle (handle);
+ mono_os_event_set (&thread_handle->event);
}
#define INTERRUPT_STATE ((MonoThreadInfoInterruptToken*) (size_t) -1)
return mono_thread_info_get_tid (info) == mono_native_thread_id_get ();
}
-void
-mono_thread_info_set_exited (THREAD_INFO_TYPE *info)
+MonoThreadInfoWaitRet
+mono_thread_info_wait_one_handle (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable)
{
- g_assert (mono_thread_info_is_current (info));
+ MonoOSEventWaitRet res;
- g_assert (info->handle);
- mono_threads_platform_set_exited (info->handle);
+ res = mono_os_event_wait_one (&thread_handle->event, timeout);
+ if (res == MONO_OS_EVENT_WAIT_RET_SUCCESS_0)
+ return MONO_THREAD_INFO_WAIT_RET_SUCCESS_0;
+ else if (res == MONO_OS_EVENT_WAIT_RET_ALERTED)
+ return MONO_THREAD_INFO_WAIT_RET_ALERTED;
+ else if (res == MONO_OS_EVENT_WAIT_RET_TIMEOUT)
+ return MONO_THREAD_INFO_WAIT_RET_TIMEOUT;
+ else
+ g_error ("%s: unknown res value %d", __func__, res);
}
-gpointer
-mono_thread_info_duplicate_handle (MonoThreadInfo *info)
+MonoThreadInfoWaitRet
+mono_thread_info_wait_multiple_handle (MonoThreadHandle **thread_handles, gsize nhandles, MonoOSEvent *background_change_event, gboolean waitall, guint32 timeout, gboolean alertable)
{
- g_assert (mono_thread_info_is_current (info));
- return mono_threads_platform_duplicate_handle (info);
+ MonoOSEventWaitRet res;
+ MonoOSEvent *thread_events [MONO_OS_EVENT_WAIT_MAXIMUM_OBJECTS];
+ gint i;
+
+ g_assert (nhandles <= MONO_OS_EVENT_WAIT_MAXIMUM_OBJECTS);
+ if (background_change_event)
+ g_assert (nhandles <= MONO_OS_EVENT_WAIT_MAXIMUM_OBJECTS - 1);
+
+ for (i = 0; i < nhandles; ++i)
+ thread_events [i] = &thread_handles [i]->event;
+
+ if (background_change_event)
+ thread_events [nhandles ++] = background_change_event;
+
+ res = mono_os_event_wait_multiple (thread_events, nhandles, waitall, timeout);
+ if (res >= MONO_OS_EVENT_WAIT_RET_SUCCESS_0 && res <= MONO_OS_EVENT_WAIT_RET_SUCCESS_0 + nhandles - 1)
+ return MONO_THREAD_INFO_WAIT_RET_SUCCESS_0 + (res - MONO_OS_EVENT_WAIT_RET_SUCCESS_0);
+ else if (res == MONO_OS_EVENT_WAIT_RET_ALERTED)
+ return MONO_THREAD_INFO_WAIT_RET_ALERTED;
+ else if (res == MONO_OS_EVENT_WAIT_RET_TIMEOUT)
+ return MONO_THREAD_INFO_WAIT_RET_TIMEOUT;
+ else
+ g_error ("%s: unknown res value %d", __func__, res);
}
#include <mono/utils/mono-linked-list-set.h>
#include <mono/utils/mono-tls.h>
#include <mono/utils/mono-coop-semaphore.h>
+#include <mono/utils/os-event.h>
#include <mono/io-layer/io-layer.h>
#endif /* #ifdef HOST_WIN32 */
+typedef struct {
+ guint32 ref;
+ MonoOSEvent event;
+} MonoThreadHandle;
+
/*
THREAD_INFO_TYPE is a way to make the mono-threads module parametric - or sort of.
The GC using mono-threads might extend the MonoThreadInfo struct to add its own
/* IO layer handle for this thread */
/* Set when the thread is started, or in _wapi_thread_duplicate () */
- HANDLE handle;
+ MonoThreadHandle *handle;
void *jit_data;
void (*thread_detach)(THREAD_INFO_TYPE *info);
void (*thread_attach)(THREAD_INFO_TYPE *info);
gboolean (*mono_method_is_critical) (void *method);
+ gboolean (*ip_in_critical_region) (MonoDomain *domain, gpointer ip);
gboolean (*mono_thread_in_critical_region) (THREAD_INFO_TYPE *info);
} MonoThreadInfoCallbacks;
mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value);
void
-mono_thread_info_exit (void);
-
-void
-mono_thread_info_set_exited (THREAD_INFO_TYPE *info);
+mono_thread_info_exit (gsize exit_code);
void
mono_thread_info_install_interrupt (void (*callback) (gpointer data), gpointer data, gboolean *interrupted);
gboolean
mono_thread_info_is_live (THREAD_INFO_TYPE *info);
-HANDLE
+MonoThreadHandle*
mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize * const stack_size, MonoNativeThreadId *out_tid);
int
mono_threads_get_max_stack_size (void);
-HANDLE
-mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
+MonoThreadHandle*
+mono_threads_open_thread_handle (MonoThreadHandle *handle);
void
-mono_threads_close_thread_handle (HANDLE handle);
+mono_threads_close_thread_handle (MonoThreadHandle *handle);
MONO_API void
mono_threads_attach_tools_thread (void);
void mono_threads_suspend_init_signals (void);
-void mono_threads_platform_init (void);
-
void mono_threads_coop_init (void);
/*
gint mono_threads_suspend_get_restart_signal (void);
gint mono_threads_suspend_get_abort_signal (void);
-void mono_threads_platform_register (THREAD_INFO_TYPE *info);
-void mono_threads_platform_unregister (THREAD_INFO_TYPE *info);
int mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid);
void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize);
gboolean mono_threads_platform_yield (void);
-void mono_threads_platform_exit (int exit_code);
-HANDLE mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
-void mono_threads_platform_close_thread_handle (HANDLE handle);
-void mono_threads_platform_set_exited (gpointer handle);
-gpointer mono_threads_platform_duplicate_handle (THREAD_INFO_TYPE *info);
+void mono_threads_platform_exit (gsize exit_code);
void mono_threads_coop_begin_global_suspend (void);
void mono_threads_coop_end_global_suspend (void);
gboolean
mono_thread_info_is_current (THREAD_INFO_TYPE *info);
-gpointer
-mono_thread_info_duplicate_handle (THREAD_INFO_TYPE *info);
+typedef enum {
+ MONO_THREAD_INFO_WAIT_RET_SUCCESS_0 = 0,
+ MONO_THREAD_INFO_WAIT_RET_ALERTED = -1,
+ MONO_THREAD_INFO_WAIT_RET_TIMEOUT = -2,
+ MONO_THREAD_INFO_WAIT_RET_FAILED = -3,
+} MonoThreadInfoWaitRet;
+
+MonoThreadInfoWaitRet
+mono_thread_info_wait_one_handle (MonoThreadHandle *handle, guint32 timeout, gboolean alertable);
+
+MonoThreadInfoWaitRet
+mono_thread_info_wait_multiple_handle (MonoThreadHandle **thread_handles, gsize nhandles, MonoOSEvent *background_change_event, gboolean waitall, guint32 timeout, gboolean alertable);
#endif /* __MONO_THREADS_H__ */
mono_os_mutex_lock (&event->mutex);
if (event->manual) {
- mono_os_event_signal (event, FALSE);
+ mono_os_event_signal (event, TRUE);
} else {
event->set_count = 1;
- mono_os_event_signal (event, TRUE);
+ mono_os_event_signal (event, FALSE);
}
mono_os_mutex_unlock (&event->mutex);
+++ /dev/null
-/*
- * w32handle.c: Generic and internal operations on handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- * Ludovic Henry (luhenry@microsoft.com)
- *
- * (C) 2002-2011 Novell, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#if !defined(HOST_WIN32)
-
-#include <glib.h>
-#include <pthread.h>
-#include <errno.h>
-#include <unistd.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <string.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_UN_H
-# include <sys/un.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-# include <sys/mman.h>
-#endif
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-#endif
-#include <sys/stat.h>
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-
-#include "w32handle.h"
-
-#include "atomic.h"
-#include "mono-logger-internals.h"
-#include "mono-os-mutex.h"
-#include "mono-proclib.h"
-#include "mono-threads.h"
-#include "mono-time.h"
-
-#undef DEBUG_REFS
-
-#define SLOT_MAX (1024 * 16)
-
-/* must be a power of 2 */
-#define HANDLE_PER_SLOT (256)
-
-#define INFINITE 0xFFFFFFFF
-
-typedef struct {
- MonoW32HandleType type;
- guint ref;
- gboolean signalled;
- mono_mutex_t signal_mutex;
- mono_cond_t signal_cond;
- gpointer specific;
-} MonoW32HandleBase;
-
-static MonoW32HandleCapability handle_caps [MONO_W32HANDLE_COUNT];
-static MonoW32HandleOps *handle_ops [MONO_W32HANDLE_COUNT];
-
-/*
- * We can hold SLOT_MAX * HANDLE_PER_SLOT handles.
- * If 4M handles are not enough... Oh, well... we will crash.
- */
-#define SLOT_INDEX(x) (x / HANDLE_PER_SLOT)
-#define SLOT_OFFSET(x) (x % HANDLE_PER_SLOT)
-
-static MonoW32HandleBase *private_handles [SLOT_MAX];
-static guint32 private_handles_count = 0;
-static guint32 private_handles_slots_count = 0;
-
-guint32 mono_w32handle_fd_reserve;
-
-/*
- * This is an internal handle which is used for handling waiting for multiple handles.
- * Threads which wait for multiple handles wait on this one handle, and when a handle
- * is signalled, this handle is signalled too.
- */
-static mono_mutex_t global_signal_mutex;
-static mono_cond_t global_signal_cond;
-
-static mono_mutex_t scan_mutex;
-
-static gboolean shutting_down = FALSE;
-
-static gboolean
-type_is_fd (MonoW32HandleType type)
-{
- switch (type) {
- case MONO_W32HANDLE_FILE:
- case MONO_W32HANDLE_CONSOLE:
- case MONO_W32HANDLE_SOCKET:
- case MONO_W32HANDLE_PIPE:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static gboolean
-mono_w32handle_lookup_data (gpointer handle, MonoW32HandleBase **handle_data)
-{
- gsize index, offset;
-
- g_assert (handle_data);
-
- index = SLOT_INDEX ((gsize) handle);
- if (index >= SLOT_MAX)
- return FALSE;
- if (!private_handles [index])
- return FALSE;
-
- offset = SLOT_OFFSET ((gsize) handle);
- if (private_handles [index][offset].type == MONO_W32HANDLE_UNUSED)
- return FALSE;
-
- *handle_data = &private_handles [index][offset];
- return TRUE;
-}
-
-MonoW32HandleType
-mono_w32handle_get_type (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data))
- return MONO_W32HANDLE_UNUSED; /* An impossible type */
-
- return handle_data->type;
-}
-
-void
-mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast)
-{
- MonoW32HandleBase *handle_data;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
-#ifdef DEBUG
- g_message ("%s: setting state of %p to %s (broadcast %s)", __func__,
- handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
-#endif
-
- if (state == TRUE) {
- /* Tell everyone blocking on a single handle */
-
- /* The condition the global signal cond is waiting on is the signalling of
- * _any_ handle. So lock it before setting the signalled state.
- */
- mono_os_mutex_lock (&global_signal_mutex);
-
- /* This function _must_ be called with
- * handle->signal_mutex locked
- */
- handle_data->signalled=state;
-
- if (broadcast == TRUE) {
- mono_os_cond_broadcast (&handle_data->signal_cond);
- } else {
- mono_os_cond_signal (&handle_data->signal_cond);
- }
-
- /* Tell everyone blocking on multiple handles that something
- * was signalled
- */
- mono_os_cond_broadcast (&global_signal_cond);
-
- mono_os_mutex_unlock (&global_signal_mutex);
- } else {
- handle_data->signalled=state;
- }
-}
-
-gboolean
-mono_w32handle_issignalled (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- return handle_data->signalled;
-}
-
-static int
-mono_w32handle_lock_signal_mutex (void)
-{
-#ifdef DEBUG
- g_message ("%s: lock global signal mutex", __func__);
-#endif
-
- mono_os_mutex_lock (&global_signal_mutex);
-
- return 0;
-}
-
-static int
-mono_w32handle_unlock_signal_mutex (void)
-{
-#ifdef DEBUG
- g_message ("%s: unlock global signal mutex", __func__);
-#endif
-
- mono_os_mutex_unlock (&global_signal_mutex);
-
- return 0;
-}
-
-int
-mono_w32handle_lock_handle (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
-
-#ifdef DEBUG
- g_message ("%s: locking handle %p", __func__, handle);
-#endif
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(0);
- }
-
- mono_w32handle_ref (handle);
-
- mono_os_mutex_lock (&handle_data->signal_mutex);
-
- return 0;
-}
-
-int
-mono_w32handle_trylock_handle (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
- int ret;
-
-#ifdef DEBUG
- g_message ("%s: locking handle %p", __func__, handle);
-#endif
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(0);
- }
-
- mono_w32handle_ref (handle);
-
- ret = mono_os_mutex_trylock (&handle_data->signal_mutex);
- if (ret != 0) {
- mono_w32handle_unref (handle);
- }
-
- return(ret);
-}
-
-int
-mono_w32handle_unlock_handle (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
-
-#ifdef DEBUG
- g_message ("%s: unlocking handle %p", __func__, handle);
-#endif
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(0);
- }
-
- mono_os_mutex_unlock (&handle_data->signal_mutex);
-
- mono_w32handle_unref (handle);
-
- return 0;
-}
-
-/*
- * wapi_init:
- *
- * Initialize the io-layer.
- */
-void
-mono_w32handle_init (void)
-{
- static gboolean initialized = FALSE;
-
- if (initialized)
- return;
-
- g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
- == MONO_W32HANDLE_COUNT);
-
- /* This is needed by the code in mono_w32handle_new_internal */
- mono_w32handle_fd_reserve = (eg_getdtablesize () + (HANDLE_PER_SLOT - 1)) & ~(HANDLE_PER_SLOT - 1);
-
- do {
- /*
- * The entries in private_handles reserved for fds are allocated lazily to
- * save memory.
- */
-
- private_handles_count += HANDLE_PER_SLOT;
- private_handles_slots_count ++;
- } while(mono_w32handle_fd_reserve > private_handles_count);
-
- mono_os_mutex_init (&scan_mutex);
-
- mono_os_cond_init (&global_signal_cond);
- mono_os_mutex_init (&global_signal_mutex);
-
- initialized = TRUE;
-}
-
-void
-mono_w32handle_cleanup (void)
-{
- int i, j, k;
-
- g_assert (!shutting_down);
- shutting_down = TRUE;
-
- /* Every shared handle we were using ought really to be closed
- * by now, but to make sure just blow them all away. The
- * exiting finalizer thread in particular races us to the
- * program exit and doesn't always win, so it can be left
- * cluttering up the shared file. Anything else left over is
- * really a bug.
- */
- for(i = SLOT_INDEX (0); private_handles[i] != NULL; i++) {
- for(j = SLOT_OFFSET (0); j < HANDLE_PER_SLOT; j++) {
- MonoW32HandleBase *handle_data = &private_handles[i][j];
- gpointer handle = GINT_TO_POINTER (i*HANDLE_PER_SLOT+j);
-
- for(k = handle_data->ref; k > 0; k--) {
- mono_w32handle_unref (handle);
- }
- }
- }
-
- for (i = 0; i < SLOT_MAX; ++i)
- g_free (private_handles [i]);
-}
-
-static void mono_w32handle_init_handle (MonoW32HandleBase *handle,
- MonoW32HandleType type, gpointer handle_specific)
-{
- g_assert (handle->ref == 0);
-
- handle->type = type;
- handle->signalled = FALSE;
- handle->ref = 1;
-
- 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));
-}
-
-/*
- * mono_w32handle_new_internal:
- * @type: Init handle to this type
- *
- * Search for a free handle and initialize it. Return the handle on
- * success and 0 on failure. This is only called from
- * mono_w32handle_new, and scan_mutex must be held.
- */
-static guint32 mono_w32handle_new_internal (MonoW32HandleType type,
- gpointer handle_specific)
-{
- guint32 i, k, count;
- static guint32 last = 0;
- gboolean retry = FALSE;
-
- /* A linear scan should be fast enough. Start from the last
- * allocation, assuming that handles are allocated more often
- * than they're freed. Leave the space reserved for file
- * descriptors
- */
-
- if (last < mono_w32handle_fd_reserve) {
- last = mono_w32handle_fd_reserve;
- } else {
- retry = TRUE;
- }
-
-again:
- count = last;
- for(i = SLOT_INDEX (count); i < private_handles_slots_count; i++) {
- if (private_handles [i]) {
- for (k = SLOT_OFFSET (count); k < HANDLE_PER_SLOT; k++) {
- MonoW32HandleBase *handle = &private_handles [i][k];
-
- if(handle->type == MONO_W32HANDLE_UNUSED) {
- last = count + 1;
-
- mono_w32handle_init_handle (handle, type, handle_specific);
- return (count);
- }
- count++;
- }
- }
- }
-
- if(retry && last > mono_w32handle_fd_reserve) {
- /* Try again from the beginning */
- last = mono_w32handle_fd_reserve;
- goto again;
- }
-
- /* Will need to expand the array. The caller will sort it out */
-
- return(0);
-}
-
-gpointer
-mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific)
-{
- guint32 handle_idx = 0;
- gpointer handle;
-
- g_assert (!shutting_down);
-
- g_assert(!type_is_fd(type));
-
- 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 */
- int idx = SLOT_INDEX (private_handles_count);
- if (idx >= SLOT_MAX) {
- break;
- }
-
- private_handles [idx] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
-
- private_handles_count += HANDLE_PER_SLOT;
- private_handles_slots_count ++;
- }
-
- mono_os_mutex_unlock (&scan_mutex);
-
- if (handle_idx == 0) {
- /* We ran out of slots */
- handle = INVALID_HANDLE_VALUE;
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle", __func__, mono_w32handle_ops_typename (type));
- goto done;
- }
-
- /* Make sure we left the space for fd mappings */
- g_assert (handle_idx >= mono_w32handle_fd_reserve);
-
- handle = GUINT_TO_POINTER (handle_idx);
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
-
-done:
- return(handle);
-}
-
-gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd,
- gpointer handle_specific)
-{
- MonoW32HandleBase *handle_data;
- int fd_index, fd_offset;
-
- g_assert (!shutting_down);
-
- g_assert(type_is_fd(type));
-
- if (fd >= mono_w32handle_fd_reserve) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is too big", __func__, mono_w32handle_ops_typename (type));
-
- return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
- }
-
- fd_index = SLOT_INDEX (fd);
- fd_offset = SLOT_OFFSET (fd);
-
- /* Initialize the array entries on demand */
- if (!private_handles [fd_index]) {
- mono_os_mutex_lock (&scan_mutex);
-
- if (!private_handles [fd_index])
- private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
-
- mono_os_mutex_unlock (&scan_mutex);
- }
-
- handle_data = &private_handles [fd_index][fd_offset];
-
- if (handle_data->type != MONO_W32HANDLE_UNUSED) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is already in use", __func__, mono_w32handle_ops_typename (type));
- /* FIXME: clean up this handle? We can't do anything
- * with the fd, cos thats the new one
- */
- return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
- }
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), GUINT_TO_POINTER(fd));
-
- mono_w32handle_init_handle (handle_data, type, handle_specific);
-
- return(GUINT_TO_POINTER(fd));
-}
-
-gboolean
-mono_w32handle_lookup (gpointer handle, MonoW32HandleType type,
- gpointer *handle_specific)
-{
- MonoW32HandleBase *handle_data;
-
- g_assert (handle_specific);
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- if (handle_data->type != type) {
- return(FALSE);
- }
-
- *handle_specific = handle_data->specific;
-
- return(TRUE);
-}
-
-static gboolean
-mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
-
-static gboolean
-mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data, guint minimum);
-
-void
-mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data)
-{
- guint32 i, k;
-
- mono_os_mutex_lock (&scan_mutex);
-
- for (i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
- if (!private_handles [i])
- continue;
- for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) {
- MonoW32HandleBase *handle_data = NULL;
- gpointer handle;
- gboolean destroy, finished;
-
- handle_data = &private_handles [i][k];
- if (handle_data->type == MONO_W32HANDLE_UNUSED)
- continue;
-
- handle = GUINT_TO_POINTER (i * HANDLE_PER_SLOT + k);
-
- if (!mono_w32handle_ref_core (handle, handle_data)) {
- /* we are racing with mono_w32handle_unref:
- * the handle ref has been decremented, but it
- * hasn't yet been destroyed. */
- continue;
- }
-
- finished = on_each (handle, handle_data->specific, user_data);
-
- /* we do not want to have to destroy the handle here,
- * as it would means the ref/unref are unbalanced */
- destroy = mono_w32handle_unref_core (handle, handle_data, 2);
- g_assert (!destroy);
-
- if (finished)
- goto done;
- }
- }
-
-done:
- mono_os_mutex_unlock (&scan_mutex);
-}
-
-typedef struct {
- MonoW32HandleType type;
- gboolean (*search_user_callback)(gpointer handle, gpointer data);
- gpointer search_user_data;
- gpointer handle;
- gpointer handle_specific;
-} SearchData;
-
-static gboolean
-search_callback (gpointer handle, gpointer handle_specific, gpointer user_data)
-{
- SearchData *search_data = (SearchData*) user_data;
-
- if (search_data->type != mono_w32handle_get_type (handle))
- return FALSE;
-
- if (!search_data->search_user_callback (handle, search_data->search_user_data))
- return FALSE;
-
- mono_w32handle_ref (handle);
- search_data->handle = handle;
- search_data->handle_specific = handle_specific;
- return TRUE;
-}
-
-/* This might list some shared handles twice if they are already
- * opened by this process, and the check function returns FALSE the
- * first time. Shared handles that are created during the search are
- * unreffed if the check function returns FALSE, so callers must not
- * rely on the handle persisting (unless the check function returns
- * TRUE)
- * The caller owns the returned handle.
- */
-gpointer mono_w32handle_search (MonoW32HandleType type,
- gboolean (*check)(gpointer test, gpointer user),
- gpointer user_data,
- gpointer *handle_specific,
- gboolean search_shared)
-{
- SearchData search_data;
-
- memset (&search_data, 0, sizeof (search_data));
- search_data.type = type;
- search_data.search_user_callback = check;
- search_data.search_user_data = user_data;
- mono_w32handle_foreach (search_callback, &search_data);
- if (handle_specific)
- *handle_specific = search_data.handle_specific;
- return search_data.handle;
-}
-
-static gboolean
-mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data)
-{
- guint old, new;
-
- do {
- old = handle_data->ref;
- if (old == 0)
- return FALSE;
-
- new = old + 1;
- } while (InterlockedCompareExchange ((gint32*) &handle_data->ref, new, old) != old);
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: ref %s handle %p, ref: %d -> %d",
- __func__, mono_w32handle_ops_typename (handle_data->type), handle, old, new);
-
- return TRUE;
-}
-
-static gboolean
-mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data, guint minimum)
-{
- MonoW32HandleType type;
- guint old, new;
-
- type = handle_data->type;
-
- do {
- old = handle_data->ref;
- if (!(old >= minimum))
- g_error ("%s: handle %p has ref %d, it should be >= %d", __func__, handle, old, minimum);
-
- new = old - 1;
- } while (InterlockedCompareExchange ((gint32*) &handle_data->ref, new, old) != old);
-
- /* handle_data might contain invalid data from now on, if
- * another thread is unref'ing this handle at the same time */
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: unref %s handle %p, ref: %d -> %d destroy: %s",
- __func__, mono_w32handle_ops_typename (type), handle, old, new, new == 0 ? "true" : "false");
-
- return new == 0;
-}
-
-void mono_w32handle_ref (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to ref handle %p, unknown handle", __func__, handle);
- return;
- }
-
- if (!mono_w32handle_ref_core (handle, handle_data))
- g_error ("%s: failed to ref handle %p", __func__, handle);
-}
-
-static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer);
-
-/* The handle must not be locked on entry to this function */
-void
-mono_w32handle_unref (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
- gboolean destroy;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to unref handle %p, unknown handle",
- __func__, handle);
- return;
- }
-
- destroy = mono_w32handle_unref_core (handle, handle_data, 1);
-
- if (destroy) {
- /* Need to copy the handle info, reset the slot in the
- * array, and _only then_ call the close function to
- * avoid race conditions (eg file descriptors being
- * closed, and another file being opened getting the
- * same fd racing the memset())
- */
- MonoW32HandleType type;
- gpointer handle_specific;
- void (*close_func)(gpointer, gpointer);
-
- type = handle_data->type;
- handle_specific = handle_data->specific;
-
- mono_os_mutex_lock (&scan_mutex);
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: destroy %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
-
- mono_os_mutex_destroy (&handle_data->signal_mutex);
- mono_os_cond_destroy (&handle_data->signal_cond);
-
- memset (handle_data, 0, sizeof (MonoW32HandleBase));
-
- mono_os_mutex_unlock (&scan_mutex);
-
- close_func = _wapi_handle_ops_get_close_func (type);
- if (close_func != NULL) {
- close_func (handle, handle_specific);
- }
-
- g_free (handle_specific);
- }
-}
-
-void
-mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops)
-{
- handle_ops [type] = ops;
-}
-
-void mono_w32handle_register_capabilities (MonoW32HandleType type,
- MonoW32HandleCapability caps)
-{
- handle_caps[type] = caps;
-}
-
-gboolean mono_w32handle_test_capabilities (gpointer handle,
- MonoW32HandleCapability caps)
-{
- MonoW32HandleBase *handle_data;
- MonoW32HandleType type;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- type = handle_data->type;
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: testing 0x%x against 0x%x (%d)", __func__,
- handle_caps[type], caps, handle_caps[type] & caps);
-
- return((handle_caps[type] & caps) != 0);
-}
-
-static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer)
-{
- if (handle_ops[type] != NULL &&
- handle_ops[type]->close != NULL) {
- return (handle_ops[type]->close);
- }
-
- return (NULL);
-}
-
-void mono_w32handle_ops_close (gpointer handle, gpointer data)
-{
- MonoW32HandleBase *handle_data;
- MonoW32HandleType type;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL &&
- handle_ops[type]->close != NULL) {
- handle_ops[type]->close (handle, data);
- }
-}
-
-void mono_w32handle_ops_details (MonoW32HandleType type, gpointer data)
-{
- if (handle_ops[type] != NULL &&
- handle_ops[type]->details != NULL) {
- handle_ops[type]->details (data);
- }
-}
-
-const gchar* mono_w32handle_ops_typename (MonoW32HandleType type)
-{
- g_assert (handle_ops [type]);
- g_assert (handle_ops [type]->typename);
- return handle_ops [type]->typename ();
-}
-
-gsize mono_w32handle_ops_typesize (MonoW32HandleType type)
-{
- g_assert (handle_ops [type]);
- g_assert (handle_ops [type]->typesize);
- return handle_ops [type]->typesize ();
-}
-
-void mono_w32handle_ops_signal (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
- MonoW32HandleType type;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
- handle_ops[type]->signal (handle);
- }
-}
-
-gboolean mono_w32handle_ops_own (gpointer handle, guint32 *statuscode)
-{
- MonoW32HandleBase *handle_data;
- MonoW32HandleType type;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
- return(handle_ops[type]->own_handle (handle, statuscode));
- } else {
- return(FALSE);
- }
-}
-
-gboolean mono_w32handle_ops_isowned (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
- MonoW32HandleType type;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) {
- return(handle_ops[type]->is_owned (handle));
- } else {
- return(FALSE);
- }
-}
-
-guint32 mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean *alerted)
-{
- MonoW32HandleBase *handle_data;
- MonoW32HandleType type;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return(WAIT_FAILED);
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL &&
- handle_ops[type]->special_wait != NULL) {
- return(handle_ops[type]->special_wait (handle, timeout, alerted));
- } else {
- return(WAIT_FAILED);
- }
-}
-
-void mono_w32handle_ops_prewait (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
- MonoW32HandleType type;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL &&
- handle_ops[type]->prewait != NULL) {
- handle_ops[type]->prewait (handle);
- }
-}
-
-static void
-spin (guint32 ms)
-{
- struct timespec sleepytime;
-
- g_assert (ms < 1000);
-
- sleepytime.tv_sec = 0;
- sleepytime.tv_nsec = ms * 1000000;
- nanosleep (&sleepytime, NULL);
-}
-
-static void
-mono_w32handle_lock_handles (gpointer *handles, gsize numhandles)
-{
- guint32 i, iter=0;
- int thr_ret;
-
- /* Lock all the handles, with backoff */
-again:
- for(i=0; i<numhandles; i++) {
- gpointer handle = handles[i];
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: attempting to lock %p", __func__, handle);
-
- thr_ret = mono_w32handle_trylock_handle (handle);
-
- if (thr_ret != 0) {
- /* Bummer */
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: attempt failed for %p: %s", __func__,
- handle, strerror (thr_ret));
-
- while (i--) {
- handle = handles[i];
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- }
-
- /* If iter ever reaches 100 the nanosleep will
- * return EINVAL immediately, but we have a
- * design flaw if that happens.
- */
- iter++;
- if(iter==100) {
- g_warning ("%s: iteration overflow!",
- __func__);
- iter=1;
- }
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Backing off for %d ms", __func__,
- iter*10);
- spin (10 * iter);
-
- goto again;
- }
- }
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Locked all handles", __func__);
-}
-
-static void
-mono_w32handle_unlock_handles (gpointer *handles, gsize numhandles)
-{
- guint32 i;
- int thr_ret;
-
- for(i=0; i<numhandles; i++) {
- gpointer handle = handles[i];
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: unlocking handle %p", __func__, handle);
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- }
-}
-
-static int
-mono_w32handle_timedwait_signal_naked (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout, gboolean poll, gboolean *alerted)
-{
- int res;
-
- if (!poll) {
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- /* This is needed when waiting for process handles */
- if (!alerted) {
- /*
- * pthread_cond_(timed)wait() can return 0 even if the condition was not
- * signalled. This happens at least on Darwin. We surface this, i.e., we
- * get spurious wake-ups.
- *
- * http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html
- */
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- if (timeout < 100) {
- /* Real timeout is less than 100ms time */
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- res = mono_os_cond_timedwait (cond, mutex, 100);
-
- /* Mask the fake timeout, this will cause
- * another poll if the cond was not really signaled
- */
- if (res == -1)
- res = 0;
- }
- }
- }
-
- return res;
-}
-
-static void
-signal_global (gpointer unused)
-{
- /* If we reach here, then interrupt token is set to the flag value, which
- * means that the target thread is either
- * - before the first CAS in timedwait, which means it won't enter the wait.
- * - it is after the first CAS, so it is already waiting, or it will enter
- * the wait, and it will be interrupted by the broadcast. */
- mono_os_mutex_lock (&global_signal_mutex);
- mono_os_cond_broadcast (&global_signal_cond);
- mono_os_mutex_unlock (&global_signal_mutex);
-}
-
-static int
-mono_w32handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
-{
- int res;
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: waiting for global", __func__);
-
- if (alerted)
- *alerted = FALSE;
-
- if (alerted) {
- mono_thread_info_install_interrupt (signal_global, NULL, alerted);
- if (*alerted)
- return 0;
- }
-
- res = mono_w32handle_timedwait_signal_naked (&global_signal_cond, &global_signal_mutex, timeout, poll, alerted);
-
- if (alerted)
- mono_thread_info_uninstall_interrupt (alerted);
-
- return res;
-}
-
-static void
-signal_handle_and_unref (gpointer handle)
-{
- MonoW32HandleBase *handle_data;
- mono_cond_t *cond;
- mono_mutex_t *mutex;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data))
- g_error ("cannot signal unknown handle %p", handle);
-
- /* If we reach here, then interrupt token is set to the flag value, which
- * means that the target thread is either
- * - before the first CAS in timedwait, which means it won't enter the wait.
- * - it is after the first CAS, so it is already waiting, or it will enter
- * the wait, and it will be interrupted by the broadcast. */
- cond = &handle_data->signal_cond;
- mutex = &handle_data->signal_mutex;
-
- mono_os_mutex_lock (mutex);
- mono_os_cond_broadcast (cond);
- mono_os_mutex_unlock (mutex);
-
- mono_w32handle_unref (handle);
-}
-
-static int
-mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
-{
- MonoW32HandleBase *handle_data;
- int res;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data))
- g_error ("cannot wait on unknown handle %p", handle);
-
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: waiting for %p (type %s)", __func__, handle,
- mono_w32handle_ops_typename (mono_w32handle_get_type (handle)));
-
- if (alerted)
- *alerted = FALSE;
-
- if (alerted) {
- mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
- if (*alerted)
- return 0;
- mono_w32handle_ref (handle);
- }
-
- res = mono_w32handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted);
-
- if (alerted) {
- mono_thread_info_uninstall_interrupt (alerted);
- if (!*alerted) {
- /* if it is alerted, then the handle is unref in the interrupt callback */
- mono_w32handle_unref (handle);
- }
- }
-
- return res;
-}
-
-static gboolean
-dump_callback (gpointer handle, gpointer handle_specific, gpointer user_data)
-{
- MonoW32HandleBase *handle_data;
-
- if (!mono_w32handle_lookup_data (handle, &handle_data))
- g_error ("cannot dump unknown handle %p", handle);
-
- g_print ("%p [%7s] signalled: %5s ref: %3d ",
- handle, mono_w32handle_ops_typename (handle_data->type), handle_data->signalled ? "true" : "false", handle_data->ref);
- mono_w32handle_ops_details (handle_data->type, handle_data->specific);
- g_print ("\n");
-
- return FALSE;
-}
-
-void mono_w32handle_dump (void)
-{
- mono_w32handle_foreach (dump_callback, NULL);
-}
-
-static gboolean
-own_if_signalled (gpointer handle, guint32 *statuscode)
-{
- if (!mono_w32handle_issignalled (handle))
- return FALSE;
-
- *statuscode = WAIT_OBJECT_0;
- mono_w32handle_ops_own (handle, statuscode);
- return TRUE;
-}
-
-static gboolean
-own_if_owned( gpointer handle, guint32 *statuscode)
-{
- if (!mono_w32handle_ops_isowned (handle))
- return FALSE;
-
- *statuscode = WAIT_OBJECT_0;
- mono_w32handle_ops_own (handle, statuscode);
- return TRUE;
-}
-
-MonoW32HandleWaitRet
-mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable)
-{
- MonoW32HandleWaitRet ret;
- gboolean alerted;
- gint64 start;
- gint thr_ret;
- guint32 statuscode = 0;
-
- alerted = FALSE;
-
- if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p has special wait",
- __func__, handle);
-
- switch (mono_w32handle_ops_specialwait (handle, timeout, alertable ? &alerted : NULL)) {
- case WAIT_OBJECT_0:
- ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
- break;
- case WAIT_ABANDONED_0:
- ret = MONO_W32HANDLE_WAIT_RET_ABANDONED_0;
- break;
- case WAIT_IO_COMPLETION:
- ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
- break;
- case WAIT_TIMEOUT:
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- break;
- case WAIT_FAILED:
- ret = MONO_W32HANDLE_WAIT_RET_FAILED;
- break;
- default:
- g_assert_not_reached ();
- }
-
- if (alerted)
- ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
-
- return ret;
- }
-
- if (!mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_WAIT)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for",
- __func__, handle);
-
- return MONO_W32HANDLE_WAIT_RET_FAILED;
- }
-
- thr_ret = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_OWN)) {
- if (own_if_owned (handle, &statuscode)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
- __func__, handle);
-
- ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
- goto done;
- }
- }
-
- if (timeout != INFINITE)
- start = mono_msec_ticks ();
-
- for (;;) {
- gint waited;
-
- if (own_if_signalled (handle, &statuscode)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
- __func__, handle);
-
- ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
- goto done;
- }
-
- mono_w32handle_ops_prewait (handle);
-
- if (timeout == INFINITE) {
- waited = mono_w32handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &alerted : NULL);
- } else {
- gint64 elapsed;
-
- elapsed = mono_msec_ticks () - start;
- if (elapsed > timeout) {
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- goto done;
- }
-
- waited = mono_w32handle_timedwait_signal_handle (handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL);
- }
-
- if (alerted) {
- ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
- goto done;
- }
-
- if (waited != 0) {
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- goto done;
- }
- }
-
-done:
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return ret;
-}
-
-MonoW32HandleWaitRet
-mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable)
-{
- MonoW32HandleWaitRet ret;
- gboolean alerted, poll;
- gint i, thr_ret;
- gint64 start;
- gpointer handles_sorted [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
- guint32 statuscodes [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS] = {0};
-
- if (nhandles == 0)
- return MONO_W32HANDLE_WAIT_RET_FAILED;
-
- if (nhandles == 1)
- return mono_w32handle_wait_one (handles [0], timeout, alertable);
-
- alerted = FALSE;
-
- if (nhandles > MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: too many handles: %zd",
- __func__, nhandles);
-
- return MONO_W32HANDLE_WAIT_RET_FAILED;
- }
-
- for (i = 0; i < nhandles; ++i) {
- if (!mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_WAIT)
- && !mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_SPECIAL_WAIT))
- {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for",
- __func__, handles [i]);
-
- return MONO_W32HANDLE_WAIT_RET_FAILED;
- }
-
- handles_sorted [i] = handles [i];
- }
-
- qsort (handles_sorted, nhandles, sizeof (gpointer), g_direct_equal);
- for (i = 1; i < nhandles; ++i) {
- if (handles_sorted [i - 1] == handles_sorted [i]) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p is duplicated",
- __func__, handles_sorted [i]);
-
- return MONO_W32HANDLE_WAIT_RET_FAILED;
- }
- }
-
- poll = FALSE;
- for (i = 0; i < nhandles; ++i) {
- if (mono_w32handle_get_type (handles [i]) == MONO_W32HANDLE_PROCESS) {
- /* Can't wait for a process handle + another handle without polling */
- poll = TRUE;
- }
- }
-
- if (timeout != INFINITE)
- start = mono_msec_ticks ();
-
- for (i = 0; i < nhandles; ++i) {
- /* Add a reference, as we need to ensure the handle wont
- * disappear from under us while we're waiting in the loop
- * (not lock, as we don't want exclusive access here) */
- mono_w32handle_ref (handles [i]);
- }
-
- for (;;) {
- gsize count, lowest;
- gboolean signalled;
- gint waited;
-
- count = 0;
- lowest = nhandles;
-
- mono_w32handle_lock_handles (handles, nhandles);
-
- for (i = 0; i < nhandles; i++) {
- if ((mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_OWN) && mono_w32handle_ops_isowned (handles [i]))
- || mono_w32handle_issignalled (handles [i]))
- {
- count ++;
-
- if (i < lowest)
- lowest = i;
- }
- }
-
- signalled = (waitall && count == nhandles) || (!waitall && count > 0);
-
- if (signalled) {
- for (i = 0; i < nhandles; i++)
- own_if_signalled (handles [i], &statuscodes [i]);
- }
-
- mono_w32handle_unlock_handles (handles, nhandles);
-
- if (signalled) {
- ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + lowest;
- for (i = lowest; i < nhandles; i++) {
- if (statuscodes [i] == WAIT_ABANDONED_0) {
- ret = MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + lowest;
- break;
- }
- }
- goto done;
- }
-
- for (i = 0; i < nhandles; i++) {
- mono_w32handle_ops_prewait (handles[i]);
-
- if (mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_SPECIAL_WAIT)
- && !mono_w32handle_issignalled (handles [i]))
- {
- mono_w32handle_ops_specialwait (handles [i], 0, alertable ? &alerted : NULL);
- }
- }
-
- thr_ret = mono_w32handle_lock_signal_mutex ();
- g_assert (thr_ret == 0);
-
- if (waitall) {
- signalled = TRUE;
- for (i = 0; i < nhandles; ++i) {
- if (!mono_w32handle_issignalled (handles [i])) {
- signalled = FALSE;
- break;
- }
- }
- } else {
- signalled = FALSE;
- for (i = 0; i < nhandles; ++i) {
- if (mono_w32handle_issignalled (handles [i])) {
- signalled = TRUE;
- break;
- }
- }
- }
-
- waited = 0;
-
- if (!signalled) {
- if (timeout == INFINITE) {
- waited = mono_w32handle_timedwait_signal (INFINITE, poll, alertable ? &alerted : NULL);
- } else {
- gint64 elapsed;
-
- elapsed = mono_msec_ticks () - start;
- if (elapsed > timeout) {
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
-
- thr_ret = mono_w32handle_unlock_signal_mutex ();
- g_assert (thr_ret == 0);
-
- goto done;
- }
-
- waited = mono_w32handle_timedwait_signal (timeout - elapsed, poll, alertable ? &alerted : NULL);
- }
- }
-
- thr_ret = mono_w32handle_unlock_signal_mutex ();
- g_assert (thr_ret == 0);
-
- if (alerted) {
- ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
- goto done;
- }
-
- if (waited != 0) {
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- goto done;
- }
- }
-
-done:
- for (i = 0; i < nhandles; i++) {
- /* Unref everything we reffed above */
- mono_w32handle_unref (handles [i]);
- }
-
- return ret;
-}
-
-MonoW32HandleWaitRet
-mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable)
-{
- MonoW32HandleWaitRet ret;
- gint64 start;
- gboolean alerted;
- gint thr_ret;
- guint32 statuscode = 0;
-
- alerted = FALSE;
-
- if (!mono_w32handle_test_capabilities (signal_handle, MONO_W32HANDLE_CAP_SIGNAL))
- return MONO_W32HANDLE_WAIT_RET_FAILED;
- if (!mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_WAIT))
- return MONO_W32HANDLE_WAIT_RET_FAILED;
-
- if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) {
- g_warning ("%s: handle %p has special wait, implement me!!", __func__, wait_handle);
- return MONO_W32HANDLE_WAIT_RET_FAILED;
- }
-
- thr_ret = mono_w32handle_lock_handle (wait_handle);
- g_assert (thr_ret == 0);
-
- mono_w32handle_ops_signal (signal_handle);
-
- if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_OWN)) {
- if (own_if_owned (wait_handle, &statuscode)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
- __func__, wait_handle);
-
- ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
- goto done;
- }
- }
-
- if (timeout != INFINITE)
- start = mono_msec_ticks ();
-
- for (;;) {
- gint waited;
-
- if (own_if_signalled (wait_handle, &statuscode)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
- __func__, wait_handle);
-
- ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
- goto done;
- }
-
- mono_w32handle_ops_prewait (wait_handle);
-
- if (timeout == INFINITE) {
- waited = mono_w32handle_timedwait_signal_handle (wait_handle, INFINITE, FALSE, alertable ? &alerted : NULL);
- } else {
- gint64 elapsed;
-
- elapsed = mono_msec_ticks () - start;
- if (elapsed > timeout) {
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- goto done;
- }
-
- waited = mono_w32handle_timedwait_signal_handle (wait_handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL);
- }
-
- if (alerted) {
- ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
- goto done;
- }
-
- if (waited != 0) {
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- goto done;
- }
- }
-
-done:
- thr_ret = mono_w32handle_unlock_handle (wait_handle);
- g_assert (thr_ret == 0);
-
- return ret;
-}
-
-#endif /* !defined(HOST_WIN32) */
+++ /dev/null
-
-#ifndef _MONO_UTILS_W32HANDLE_H_
-#define _MONO_UTILS_W32HANDLE_H_
-
-#include <config.h>
-#include <glib.h>
-
-#ifndef INVALID_HANDLE_VALUE
-#define INVALID_HANDLE_VALUE (gpointer)-1
-#endif
-
-#define MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS 64
-
-typedef enum {
- MONO_W32HANDLE_UNUSED = 0,
- MONO_W32HANDLE_FILE,
- MONO_W32HANDLE_CONSOLE,
- MONO_W32HANDLE_THREAD,
- MONO_W32HANDLE_SEM,
- MONO_W32HANDLE_MUTEX,
- MONO_W32HANDLE_EVENT,
- MONO_W32HANDLE_SOCKET,
- MONO_W32HANDLE_FIND,
- MONO_W32HANDLE_PROCESS,
- MONO_W32HANDLE_PIPE,
- MONO_W32HANDLE_NAMEDMUTEX,
- MONO_W32HANDLE_NAMEDSEM,
- MONO_W32HANDLE_NAMEDEVENT,
- MONO_W32HANDLE_COUNT
-} MonoW32HandleType;
-
-typedef struct
-{
- void (*close)(gpointer handle, gpointer data);
-
- /* SignalObjectAndWait */
- void (*signal)(gpointer signal);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects,
- * with the handle locked (shared handles aren't locked.)
- * Returns TRUE if ownership was established, false otherwise.
- * If TRUE, *statuscode contains a status code such as
- * WAIT_OBJECT_0 or WAIT_ABANDONED_0.
- */
- gboolean (*own_handle)(gpointer handle, guint32 *statuscode);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects, if the
- * handle in question is "ownable" (ie mutexes), to see if the current
- * thread already owns this handle
- */
- gboolean (*is_owned)(gpointer handle);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects,
- * if the handle in question needs a special wait function
- * instead of using the normal handle signal mechanism.
- * Returns the WaitForSingleObject return code.
- */
- guint32 (*special_wait)(gpointer handle, guint32 timeout, gboolean *alerted);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects,
- * if the handle in question needs some preprocessing before the
- * signal wait.
- */
- void (*prewait)(gpointer handle);
-
- /* Called when dumping the handles */
- void (*details)(gpointer data);
-
- /* Called to get the name of the handle type */
- const gchar* (*typename) (void);
-
- /* Called to get the size of the handle type */
- gsize (*typesize) (void);
-} MonoW32HandleOps;
-
-typedef enum {
- MONO_W32HANDLE_CAP_WAIT = 0x01,
- MONO_W32HANDLE_CAP_SIGNAL = 0x02,
- MONO_W32HANDLE_CAP_OWN = 0x04,
- MONO_W32HANDLE_CAP_SPECIAL_WAIT = 0x08,
-} MonoW32HandleCapability;
-
-extern guint32 mono_w32handle_fd_reserve;
-
-void
-mono_w32handle_init (void);
-
-void
-mono_w32handle_cleanup (void);
-
-void
-mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops);
-
-gpointer
-mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific);
-
-gpointer
-mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific);
-
-MonoW32HandleType
-mono_w32handle_get_type (gpointer handle);
-
-gboolean
-mono_w32handle_lookup (gpointer handle, MonoW32HandleType type, gpointer *handle_specific);
-
-gpointer
-mono_w32handle_search (MonoW32HandleType type, gboolean (*check)(gpointer, gpointer), gpointer user_data, gpointer *handle_specific, gboolean search_shared);
-
-void
-mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data);
-
-void
-mono_w32handle_dump (void);
-
-void
-mono_w32handle_ref (gpointer handle);
-
-void
-mono_w32handle_unref (gpointer handle);
-
-void
-mono_w32handle_register_capabilities (MonoW32HandleType type, MonoW32HandleCapability caps);
-
-gboolean
-mono_w32handle_test_capabilities (gpointer handle, MonoW32HandleCapability caps);
-
-void
-mono_w32handle_ops_close (gpointer handle, gpointer data);
-
-void
-mono_w32handle_ops_signal (gpointer handle);
-
-gboolean
-mono_w32handle_ops_own (gpointer handle, guint32 *statuscode);
-
-gboolean
-mono_w32handle_ops_isowned (gpointer handle);
-
-guint32
-mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean *alerted);
-
-void
-mono_w32handle_ops_prewait (gpointer handle);
-
-void
-mono_w32handle_ops_details (MonoW32HandleType type, gpointer data);
-
-const gchar*
-mono_w32handle_ops_typename (MonoW32HandleType type);
-
-gsize
-mono_w32handle_ops_typesize (MonoW32HandleType type);
-
-void
-mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast);
-
-gboolean
-mono_w32handle_issignalled (gpointer handle);
-
-int
-mono_w32handle_lock_handle (gpointer handle);
-
-int
-mono_w32handle_trylock_handle (gpointer handle);
-
-int
-mono_w32handle_unlock_handle (gpointer handle);
-
-typedef enum {
- MONO_W32HANDLE_WAIT_RET_SUCCESS_0 = 0,
- MONO_W32HANDLE_WAIT_RET_ABANDONED_0 = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS,
- MONO_W32HANDLE_WAIT_RET_ALERTED = -1,
- MONO_W32HANDLE_WAIT_RET_TIMEOUT = -2,
- MONO_W32HANDLE_WAIT_RET_FAILED = -3,
-} MonoW32HandleWaitRet;
-
-MonoW32HandleWaitRet
-mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable);
-
-MonoW32HandleWaitRet
-mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable);
-
-MonoW32HandleWaitRet
-mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable);
-
-#endif /* _MONO_UTILS_W32HANDLE_H_ */
<ClCompile Include="..\mono\metadata\assembly.c" />\r
<ClCompile Include="..\mono\metadata\attach.c" />\r
<ClCompile Include="..\mono\metadata\boehm-gc.c" />\r
+ <ClCompile Include="..\mono\metadata\class-accessors.c" />\r
<ClCompile Include="..\mono\metadata\class.c" />\r
<ClCompile Include="..\mono\metadata\cominterop.c" />\r
<ClCompile Include="..\mono\metadata\console-win32.c" />\r
<ClCompile Include="..\mono\metadata\icall-windows.c" />\r
<ClCompile Include="..\mono\metadata\marshal-windows.c" />\r
<ClCompile Include="..\mono\metadata\mono-security-windows.c" />\r
- <ClCompile Include="..\mono\metadata\process-windows.c" />\r
<ClCompile Include="..\mono\metadata\w32mutex-win32.c" />\r
<ClCompile Include="..\mono\metadata\w32semaphore-win32.c" />\r
<ClCompile Include="..\mono\metadata\w32event-win32.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c" />\r
<ClCompile Include="..\mono\metadata\coree.c" />\r
<ClCompile Include="..\mono\metadata\custom-attrs.c" />\r
<ClCompile Include="..\mono\metadata\debug-helpers.c" />\r
<ClCompile Include="..\mono\metadata\number-ms.c" />\r
<ClCompile Include="..\mono\metadata\object.c" />\r
<ClCompile Include="..\mono\metadata\opcodes.c" />\r
- <ClCompile Include="..\mono\metadata\process.c" />\r
<ClCompile Include="..\mono\metadata\profiler.c" />\r
<ClCompile Include="..\mono\metadata\rand.c" />\r
<ClCompile Include="..\mono\metadata\reflection.c" />\r
<ClInclude Include="..\mono\metadata\marshal-windows-internals.h" />\r
<ClInclude Include="..\mono\metadata\mono-security-windows-internals.h" />\r
<ClInclude Include="..\mono\metadata\number-ms.h" />\r
- <ClInclude Include="..\mono\metadata\process-internals.h" />\r
- <ClInclude Include="..\mono\metadata\process-windows-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\w32process.h" />\r
+ <ClInclude Include="..\mono\metadata\w32process-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\w32process-win32-internals.h" />\r
<ClInclude Include="..\mono\metadata\remoting.h" />\r
<ClInclude Include="..\mono\metadata\seq-points-data.h" />\r
<ClInclude Include="..\mono\metadata\sgen-bridge-internals.h" />\r
<ClInclude Include="..\mono\metadata\object-internals.h" />\r
<ClInclude Include="..\mono\metadata\object.h" />\r
<ClInclude Include="..\mono\metadata\opcodes.h" />\r
- <ClInclude Include="..\mono\metadata\process.h" />\r
<ClInclude Include="..\mono\metadata\profiler-private.h" />\r
<ClInclude Include="..\mono\metadata\profiler.h" />\r
<ClInclude Include="..\mono\metadata\rand.h" />\r
<ClCompile Include="..\mono\metadata\opcodes.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process.c">\r
+ <ClCompile Include="..\mono\metadata\w32process.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\profiler.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\socket-io-windows.c">\r
- <Filter>Source Files</Filter>\r
+ <Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\file-io-windows.c">\r
<Filter>Source Files</Filter>\r
<ClCompile Include="..\mono\metadata\mono-security-windows.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process-windows.c">\r
+ <ClCompile Include="..\mono\metadata\class-accessors.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClInclude Include="..\mono\metadata\opcodes.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\mono\metadata\process.h">\r
+ <ClInclude Include="..\mono\metadata\w32process.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\w32process-internals.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\w32process-win32-internals.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
<ClInclude Include="..\mono\metadata\profiler.h">\r
<ClInclude Include="..\mono\metadata\mono-security-windows-internals.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\mono\metadata\process-windows-internals.h">\r
- <Filter>Header Files</Filter>\r
- </ClInclude>\r
- <ClInclude Include="..\mono\metadata\process-internals.h">\r
- <Filter>Header Files</Filter>\r
- </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<Filter Include="Header Files">\r
<ClCompile Include="..\mono\metadata\metadata.c" />\r
<ClCompile Include="..\mono\metadata\monitor.c" />\r
<ClCompile Include="..\mono\metadata\mono-config.c" />\r
- <ClCompile Include="..\mono\metadata\process-windows.c" />\r
<ClCompile Include="..\mono\utils\mono-dl.c" />\r
<ClCompile Include="..\mono\metadata\object.c" />\r
- <ClCompile Include="..\mono\metadata\process.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c" />\r
<ClCompile Include="..\mono\metadata\profiler.c" />\r
<ClCompile Include="..\mono\metadata\rand.c" />\r
<ClCompile Include="..\mono\metadata\reflection.c" />\r
<ClCompile Include="..\mono\metadata\object.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process.c">\r
+ <ClCompile Include="..\mono\metadata\w32process.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\profiler.c">\r
<ClCompile Include="..\tools\pedump\pedump.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process-windows.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
<ClCompile Include="..\mono\metadata\marshal-windows.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
</project>
<project dir="tools/mono-api-html" library="mono-api-html-net_4_x">
<boot></boot>
- <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/net_4_x/mscorlib.dll -debug -optimize /noconfig -r:Mono.Cecil -r:System.Xml -r:System.Core -r:System -r:System.Xml.Linq</flags>
+ <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/net_4_x/mscorlib.dll -debug -optimize /noconfig -r:System.Xml -r:System.Core -r:System -r:System.Xml.Linq</flags>
<output>mono-api-html.exe</output>
<built_sources></built_sources>
<library_output>./../../class/lib/net_4_x/mono-api-html.exe</library_output>
<resources></resources>
<response>System.Security.Cryptography.Cng.dll.sources</response>
</project>
+ <project dir="class/Mono.Btls.Interface" library="Mono.Btls.Interface-monodroid">
+ <boot>false</boot>
+ <flags>/codepage:65001 -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MONO -d:MOBILE,MOBILE_LEGACY -d:MOBILE_DYNAMIC -d:MONODROID -d:ANDROID -d:NETSTANDARD -nowarn:1699 -nostdlib -r:./../../class/lib/monodroid/mscorlib.dll -debug -optimize /noconfig -unsafe -nowarn:1030 -keyfile:../mono.pub -delaysign -d:SECURITY_DEP -r:./../../class/lib/monodroid/System.dll -r:./../../class/lib/monodroid/Mono.Security.dll</flags>
+ <output>Mono.Btls.Interface.dll</output>
+ <built_sources></built_sources>
+ <library_output>./../../class/lib/monodroid/Mono.Btls.Interface.dll</library_output>
+ <fx_version>2.1</fx_version>
+ <profile>monodroid</profile>
+ <resources></resources>
+ <response>Mono.Btls.Interface.dll.sources</response>
+ </project>
<project dir="class/corlib" library="corlib-monotouch">
<boot>true</boot>
<flags>/codepage:65001 -unsafe -nostdlib -nowarn:612,618,1635 -d:INSIDE_CORLIB,MONO_CULTURE_DATA -d:LIBC -d:FEATURE_PAL,GENERICS_WORK,FEATURE_LIST_PREDICATES,FEATURE_SERIALIZATION,FEATURE_ASCII,FEATURE_LATIN1,FEATURE_UTF7,FEATURE_UTF32,MONO_HYBRID_ENCODING_SUPPORT,FEATURE_ASYNC_IO,NEW_EXPERIMENTAL_ASYNC_IO,FEATURE_UTF32,FEATURE_EXCEPTIONDISPATCHINFO,FEATURE_CORRUPTING_EXCEPTIONS,FEATURE_EXCEPTION_NOTIFICATIONS,FEATURE_STRONGNAME_MIGRATION,FEATURE_USE_LCID,FEATURE_FUSION,FEATURE_CRYPTO,FEATURE_X509_SECURESTRINGS,FEATURE_SYNCHRONIZATIONCONTEXT,FEATURE_SYNCHRONIZATIONCONTEXT_WAIT,HAS_CORLIB_CONTRACTS -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MOBILE,MOBILE_LEGACY -d:MONO -d:MONOTOUCH -d:DISABLE_REMOTING -d:DISABLE_COM -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NETSTANDARD -nowarn:1699 -nostdlib -debug -d:FULL_AOT_RUNTIME -optimize /noconfig -d:FEATURE_PAL,GENERICS_WORK,FEATURE_LIST_PREDICATES,FEATURE_SERIALIZATION,FEATURE_ASCII,FEATURE_LATIN1,FEATURE_UTF7,FEATURE_UTF32,MONO_HYBRID_ENCODING_SUPPORT,FEATURE_ASYNC_IO,NEW_EXPERIMENTAL_ASYNC_IO,FEATURE_UTF32,FEATURE_EXCEPTIONDISPATCHINFO,FEATURE_CORRUPTING_EXCEPTIONS,FEATURE_EXCEPTION_NOTIFICATIONS,FEATURE_STRONGNAME_MIGRATION,FEATURE_USE_LCID,FEATURE_FUSION,FEATURE_CRYPTO,FEATURE_X509_SECURESTRINGS,FEATURE_SYNCHRONIZATIONCONTEXT,FEATURE_SYNCHRONIZATIONCONTEXT_WAIT,HAS_CORLIB_CONTRACTS -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -resource:resources/charinfo.nlp -resource:resources/collation.core.bin -resource:resources/collation.tailoring.bin -resource:resources/collation.cjkCHS.bin -resource:resources/collation.cjkCHT.bin -resource:resources/collation.cjkJA.bin -resource:resources/collation.cjkKO.bin -resource:resources/collation.cjkKOlv2.bin --runtime:v4</flags>
</project>
<project dir="class/System" library="System-xammac">
<boot>false</boot>
- <flags>/codepage:65001 -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MONO -d:MOBILE -d:MOBILE_DYNAMIC -d:XAMMAC -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:XAMARIN_MODERN -d:NETSTANDARD -nowarn:1699 -nostdlib -r:./../../class/lib/xammac/mscorlib.dll -debug -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -d:MONO_FEATURE_BTLS -d:INSIDE_SYSTEM -d:SECURITY_DEP -nowarn:618,1635 -d:SECURITY_DEP -d:XML_DEP -r:./../../class/lib/xammac/System.Xml.dll -r:MonoSecurity=./../../class/lib/xammac/Mono.Security.dll</flags>
+ <flags>/codepage:65001 -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MONO -d:MOBILE -d:MOBILE_DYNAMIC -d:XAMMAC -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:XAMARIN_MODERN -d:NETSTANDARD -nowarn:1699 -nostdlib -r:./../../class/lib/xammac/mscorlib.dll -debug -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -d:INSIDE_SYSTEM -d:SECURITY_DEP -nowarn:618,1635 -d:SECURITY_DEP -d:XML_DEP -r:./../../class/lib/xammac/System.Xml.dll -r:MonoSecurity=./../../class/lib/xammac/Mono.Security.dll</flags>
<output>System.dll</output>
<built_sources></built_sources>
<library_output>./../../class/lib/xammac/System.dll</library_output>
</project>
<project dir="class/System" library="System-bare-xammac">
<boot>false</boot>
- <flags>/codepage:65001 -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MONO -d:MOBILE -d:MOBILE_DYNAMIC -d:XAMMAC -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:XAMARIN_MODERN -d:NETSTANDARD -nowarn:1699 -nostdlib -r:./../../class/lib/xammac/mscorlib.dll -debug -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -d:MONO_FEATURE_BTLS -d:INSIDE_SYSTEM -d:SECURITY_DEP -nowarn:618,1635</flags>
+ <flags>/codepage:65001 -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MONO -d:MOBILE -d:MOBILE_DYNAMIC -d:XAMMAC -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:XAMARIN_MODERN -d:NETSTANDARD -nowarn:1699 -nostdlib -r:./../../class/lib/xammac/mscorlib.dll -debug -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -d:INSIDE_SYSTEM -d:SECURITY_DEP -nowarn:618,1635</flags>
<output>System.dll</output>
<built_sources></built_sources>
<library_output>./../../class/lib/xammac/bare/System.dll</library_output>
</project>
<project dir="class/System" library="System-secxml-xammac">
<boot>false</boot>
- <flags>/codepage:65001 -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MONO -d:MOBILE -d:MOBILE_DYNAMIC -d:XAMMAC -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:XAMARIN_MODERN -d:NETSTANDARD -nowarn:1699 -nostdlib -r:./../../class/lib/xammac/mscorlib.dll -debug -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -d:MONO_FEATURE_BTLS -d:INSIDE_SYSTEM -d:SECURITY_DEP -nowarn:618,1635 -d:SECURITY_DEP -d:XML_DEP -r:./../../class/lib/xammac/bare/System.Xml.dll -r:MonoSecurity=./../../class/lib/xammac/Mono.Security.dll</flags>
+ <flags>/codepage:65001 -d:NET_1_1 -d:NET_2_0 -d:NET_2_1 -d:NET_3_5 -d:NET_4_0 -d:NET_4_5 -d:MONO -d:MOBILE -d:MOBILE_DYNAMIC -d:XAMMAC -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:XAMARIN_MODERN -d:NETSTANDARD -nowarn:1699 -nostdlib -r:./../../class/lib/xammac/mscorlib.dll -debug -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -d:INSIDE_SYSTEM -d:SECURITY_DEP -nowarn:618,1635 -d:SECURITY_DEP -d:XML_DEP -r:./../../class/lib/xammac/bare/System.Xml.dll -r:MonoSecurity=./../../class/lib/xammac/Mono.Security.dll</flags>
<output>System.dll</output>
<built_sources></built_sources>
<library_output>./../../class/lib/xammac/secxml/System.dll</library_output>
</project>
<project dir="class/System" library="System-xammac_net_4_5">
<boot>false</boot>
- <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -resource:resources/Asterisk.wav -resource:resources/Beep.wav -resource:resources/Exclamation.wav -resource:resources/Hand.wav -resource:resources/Question.wav -d:MONO_FEATURE_BTLS -d:SECURITY_DEP -d:XML_DEP -d:MONO_SECURITY_ALIAS -d:CONFIGURATION_DEP -r:./../../class/lib/xammac_net_4_5/System.Xml.dll -r:./../../class/lib/xammac_net_4_5/System.Configuration.dll -r:MonoSecurity=./../../class/lib/xammac_net_4_5/Mono.Security.dll</flags>
+ <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -resource:resources/Asterisk.wav -resource:resources/Beep.wav -resource:resources/Exclamation.wav -resource:resources/Hand.wav -resource:resources/Question.wav -d:SECURITY_DEP -d:XML_DEP -d:MONO_SECURITY_ALIAS -d:CONFIGURATION_DEP -r:./../../class/lib/xammac_net_4_5/System.Xml.dll -r:./../../class/lib/xammac_net_4_5/System.Configuration.dll -r:MonoSecurity=./../../class/lib/xammac_net_4_5/Mono.Security.dll</flags>
<output>System.dll</output>
<built_sources></built_sources>
<library_output>./../../class/lib/xammac_net_4_5/System.dll</library_output>
</project>
<project dir="class/System" library="System-bare-xammac_net_4_5">
<boot>false</boot>
- <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -resource:resources/Asterisk.wav -resource:resources/Beep.wav -resource:resources/Exclamation.wav -resource:resources/Hand.wav -resource:resources/Question.wav -d:MONO_FEATURE_BTLS</flags>
+ <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -resource:resources/Asterisk.wav -resource:resources/Beep.wav -resource:resources/Exclamation.wav -resource:resources/Hand.wav -resource:resources/Question.wav</flags>
<output>System.dll</output>
<built_sources></built_sources>
<library_output>./../../class/lib/xammac_net_4_5/bare/System.dll</library_output>
</project>
<project dir="class/System" library="System-secxml-xammac_net_4_5">
<boot>false</boot>
- <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -resource:resources/Asterisk.wav -resource:resources/Beep.wav -resource:resources/Exclamation.wav -resource:resources/Hand.wav -resource:resources/Question.wav -d:MONO_FEATURE_BTLS -d:SECURITY_DEP -d:XML_DEP -d:MONO_SECURITY_ALIAS -r:./../../class/lib/xammac_net_4_5/bare/System.Xml.dll -r:MonoSecurity=./../../class/lib/xammac_net_4_5/Mono.Security.dll</flags>
+ <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -d:CONFIGURATION_2_0 -d:FEATURE_PAL,SYSTEM_NAMESPACE,MONO,PLATFORM_UNIX -d:MONO_FEATURE_PROCESS_START -d:MONO_FEATURE_THREAD_ABORT -d:MONO_FEATURE_THREAD_SUSPEND_RESUME -d:MONO_FEATURE_MULTIPLE_APPDOMAINS -unsafe -resource:resources/Asterisk.wav -resource:resources/Beep.wav -resource:resources/Exclamation.wav -resource:resources/Hand.wav -resource:resources/Question.wav -d:SECURITY_DEP -d:XML_DEP -d:MONO_SECURITY_ALIAS -r:./../../class/lib/xammac_net_4_5/bare/System.Xml.dll -r:MonoSecurity=./../../class/lib/xammac_net_4_5/Mono.Security.dll</flags>
<output>System.dll</output>
<built_sources></built_sources>
<library_output>./../../class/lib/xammac_net_4_5/secxml/System.dll</library_output>
<resources></resources>
<response>System.Net.Http.WebRequest.dll.sources</response>
</project>
- <project dir="class/Mono.Btls.Interface" library="Mono.Btls.Interface-xammac_net_4_5">
- <boot>false</boot>
- <flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -unsafe -nowarn:1030 -keyfile:../mono.pub -delaysign -d:SECURITY_DEP -r:./../../class/lib/xammac_net_4_5/System.dll -r:./../../class/lib/xammac_net_4_5/Mono.Security.dll</flags>
- <output>Mono.Btls.Interface.dll</output>
- <built_sources></built_sources>
- <library_output>./../../class/lib/xammac_net_4_5/Mono.Btls.Interface.dll</library_output>
- <fx_version>4.5</fx_version>
- <profile>xammac_net_4_5</profile>
- <resources></resources>
- <response>Mono.Btls.Interface.dll.sources</response>
- </project>
<project dir="class/System.Runtime.InteropServices.RuntimeInformation" library="System.Runtime.InteropServices.RuntimeInformation-xammac_net_4_5">
<boot>false</boot>
<flags>/codepage:65001 -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -nowarn:1699 -nostdlib -r:./../../class/lib/xammac_net_4_5/mscorlib.dll -debug -d:FEATURE_INTERCEPTABLE_THREADPOOL_CALLBACK -d:NO_SYSTEM_DRAWING_DEPENDENCY -d:NO_WINFORMS_DEPENDENCY -d:NO_SYSTEM_WEB_DEPENDENCY -d:XAMMAC_4_5 -d:XAMARIN_MODERN -optimize /noconfig -r:./../../class/lib/xammac_net_4_5/System.dll</flags>
${TESTCMD} --label=System.Data --timeout=5m make -w -C mcs/class/System.Data run-test
${TESTCMD} --label=System.Data.OracleClient --timeout=5m make -w -C mcs/class/System.Data.OracleClient run-test;
${TESTCMD} --label=System.Design --timeout=5m make -w -C mcs/class/System.Design run-test;
-if [[ -n "${ghprbPullId}" ]] && [[ ${label} == w* ]]; then ${TESTCMD} --label=Mono.Posix --skip; else ${TESTCMD} --label=Mono.Posix --timeout=5m make -w -C mcs/class/Mono.Posix run-test; fi
+${TESTCMD} --label=Mono.Posix --timeout=5m make -w -C mcs/class/Mono.Posix run-test
${TESTCMD} --label=System.Web --timeout=30m make -w -C mcs/class/System.Web run-test
${TESTCMD} --label=System.Web.Services --timeout=5m make -w -C mcs/class/System.Web.Services run-test
${TESTCMD} --label=System.Runtime.SFS --timeout=5m make -w -C mcs/class/System.Runtime.Serialization.Formatters.Soap run-test;
while (zs->avail_out > 0) {
if (zs->avail_in == 0) {
n = stream->func (stream->buffer, BUFFER_SIZE, stream->gchandle);
+ n = n < 0 ? 0 : n;
stream->total_in += n;
- if (n <= 0) {
- stream->eof = TRUE;
- }
zs->next_in = stream->buffer;
- zs->avail_in = n < 0 ? 0 : n;
+ zs->avail_in = n;
}
- if (zs->avail_in == 0 && (zs->total_in == 0 || stream->total_in == zs->total_in))
- return Z_STREAM_END;
+ if (zs->avail_in == 0 && zs->total_in == 0)
+ return 0;
status = inflate (stream->stream, Z_SYNC_FLUSH);
if (status == Z_STREAM_END) {
stream->eof = TRUE;
break;
+ } else if (status == Z_BUF_ERROR && stream->total_in == zs->total_in) {
+ stream->eof = TRUE;
+ break;
} else if (status != Z_OK) {
return status;
}
if (i == MONO_CEE_CASTCLASS || i == MONO_CEE_ISINST) {
guint32 token = read32 (ip + 1);
MonoClass *k = mono_class_get (method->klass->image, token);
- if (k && k->flags & TYPE_ATTRIBUTE_SEALED)
+ if (k && mono_class_get_flags (k) & TYPE_ATTRIBUTE_SEALED)
cast_sealed++;
- if (k && k->flags & TYPE_ATTRIBUTE_INTERFACE)
+ if (k && mono_class_get_flags (k) & TYPE_ATTRIBUTE_INTERFACE)
cast_iface++;
total_cast++;
}
MonoMethod *cm = mono_get_method (method->klass->image, read32 (ip + 1), NULL);
if (cm && !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
nonvirt_callvirt++;
- if (cm && (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
+ if (cm && (mono_class_get_flags (cm->klass) & TYPE_ATTRIBUTE_INTERFACE))
iface_callvirt++;
total_callvirt++;
}
MonoClass *parent;
int depth = 1;
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_INTERFACE) {
num_ifaces++;
return;
}