From a3be248d3fbc278398c1937788ebce2a7b0c211d Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 27 Feb 2019 18:21:34 -0400 Subject: [PATCH] [corlib] Simplify RuntimeInformation by getting OS name from the runtime (#13164) We can get the the OS name similar to the architecture from the value that is used by the runtime for DllMaps. Cached the values into static fields so we only need to do the runtime icall once. Added all the existing OS names recognized by DllMap to RuntimeInformation. This also allows us to mark some corlib/System tests that hang the runtime on AIX as non-working. --- .../System/Test/System.Diagnostics/ProcessTest.cs | 6 + .../RuntimeInformation.cs | 132 ++++++++++++++------- .../Test/System.Threading/InterlockedTest.cs | 28 +++++ mono/metadata/icall-def.h | 3 +- mono/metadata/icall.c | 12 +- 5 files changed, 134 insertions(+), 47 deletions(-) diff --git a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs index fd382999eb1..b1fc4962cb6 100644 --- a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs @@ -1035,6 +1035,12 @@ namespace MonoTests.System.Diagnostics [NUnit.Framework.Category ("MobileNotWorking")] public void StandardInputWrite () { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("AIX"))) + { + // This test is broken on AIX because the fork child seems to become comatose. + Assert.Ignore ("Skipping on AIX/i"); + } + var psi = GetEchoCrossPlatformStartInfo (); psi.RedirectStandardInput = true; psi.RedirectStandardOutput = true; diff --git a/mcs/class/corlib/System.Runtime.InteropServices.RuntimeInformation/RuntimeInformation.cs b/mcs/class/corlib/System.Runtime.InteropServices.RuntimeInformation/RuntimeInformation.cs index 7b11484ead0..8e2c82b19ef 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices.RuntimeInformation/RuntimeInformation.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices.RuntimeInformation/RuntimeInformation.cs @@ -36,13 +36,93 @@ namespace System.Runtime.InteropServices { public static class RuntimeInformation { - /* gets the runtime's arch from the value it uses for DllMap */ - static extern string RuntimeArchitecture + static readonly Architecture _osArchitecture; + static readonly Architecture _processArchitecture; + static readonly OSPlatform _osPlatform; + + static RuntimeInformation () { - [MethodImpl (MethodImplOptions.InternalCall)] - get; + // we can use the runtime's compiled config options for DllMaps here + // process architecure for us is runtime architecture + // see for values: mono-config.c + var runtimeArchitecture = GetRuntimeArchitecture (); + var osName = GetOSName (); + + // check OS/process architecture + switch (runtimeArchitecture) { + case "arm": + _osArchitecture = Environment.Is64BitOperatingSystem ? Architecture.Arm64 : Architecture.Arm; + _processArchitecture = Architecture.Arm; + break; + case "armv8": + _osArchitecture = Environment.Is64BitOperatingSystem ? Architecture.Arm64 : Architecture.Arm; + _processArchitecture = Architecture.Arm64; + break; + case "x86": + _osArchitecture = Environment.Is64BitOperatingSystem ? Architecture.X64 : Architecture.X86; + _processArchitecture = Architecture.X86; + break; + case "x86-64": + _osArchitecture = Environment.Is64BitOperatingSystem ? Architecture.X64 : Architecture.X86; + _processArchitecture = Architecture.X64; + break; + // upstream only has these values; try to pretend we're x86 if nothing matches + // want more? bug: https://github.com/dotnet/corefx/issues/30706 + default: + _osArchitecture = Environment.Is64BitOperatingSystem ? Architecture.X64 : Architecture.X86; + _processArchitecture = Environment.Is64BitProcess ? Architecture.X64 : Architecture.X86; + break; + } + + // check OS platform + switch (osName) { + case "linux": + _osPlatform = OSPlatform.Linux; + break; + case "osx": + _osPlatform = OSPlatform.OSX; + break; + case "windows": + _osPlatform = OSPlatform.Windows; + break; + case "solaris": + _osPlatform = OSPlatform.Create ("SOLARIS"); + break; + case "freebsd": + _osPlatform = OSPlatform.Create ("FREEBSD"); + break; + case "netbsd": + _osPlatform = OSPlatform.Create ("NETBSD"); + break; + case "openbsd": + _osPlatform = OSPlatform.Create ("OPENBSD"); + break; + case "aix": + _osPlatform = OSPlatform.Create ("AIX"); + break; + case "hpux": + _osPlatform = OSPlatform.Create ("HPUX"); + break; + case "haiku": + _osPlatform = OSPlatform.Create ("HAIKU"); + break; + case "wasm": + _osPlatform = OSPlatform.Create ("WEBASSEMBLY"); + break; + default: + _osPlatform = OSPlatform.Create ("UNKNOWN"); + break; + } } + /* gets the runtime's arch from the value it uses for DllMap */ + [MethodImpl (MethodImplOptions.InternalCall)] + static extern string GetRuntimeArchitecture (); + + /* gets the runtime's OS from the value it uses for DllMap */ + [MethodImpl (MethodImplOptions.InternalCall)] + static extern string GetOSName (); + public static string FrameworkDescription { get { return "Mono " + Mono.Runtime.GetDisplayName (); @@ -51,20 +131,7 @@ namespace System.Runtime.InteropServices public static bool IsOSPlatform (OSPlatform osPlatform) { -#if WASM - return osPlatform == OSPlatform.Create ("WEBASSEMBLY"); -#else - switch (Environment.Platform) { - case PlatformID.Win32NT: - return osPlatform == OSPlatform.Windows; - case PlatformID.MacOSX: - return osPlatform == OSPlatform.OSX; - case PlatformID.Unix: - return osPlatform == OSPlatform.Linux; - default: - return false; - } -#endif + return _osPlatform == osPlatform; } public static string OSDescription @@ -83,17 +150,7 @@ namespace System.Runtime.InteropServices { get { - switch (RuntimeArchitecture) { - case "arm": - case "armv8": - return Environment.Is64BitOperatingSystem ? Architecture.Arm64 : Architecture.Arm; - case "x86": - case "x86-64": - // upstream only has these values; try to pretend we're x86 if nothing matches - // want more? bug: https://github.com/dotnet/corefx/issues/30706 - default: - return Environment.Is64BitOperatingSystem ? Architecture.X64 : Architecture.X86; - } + return _osArchitecture; } } @@ -101,22 +158,7 @@ namespace System.Runtime.InteropServices { get { - // we can use the runtime's compiled config options for DllMaps here - // process architecure for us is runtime architecture (OS is much harder) - // see for values: mono-config.c - switch (RuntimeArchitecture) { - case "x86": - return Architecture.X86; - case "x86-64": - return Architecture.X64; - case "arm": - return Architecture.Arm; - case "armv8": - return Architecture.Arm64; - // see comment in OSArchiteture default case - default: - return Environment.Is64BitProcess ? Architecture.X64 : Architecture.X86; - } + return _processArchitecture; } } } diff --git a/mcs/class/corlib/Test/System.Threading/InterlockedTest.cs b/mcs/class/corlib/Test/System.Threading/InterlockedTest.cs index ac4d7d66479..20ed84b0a19 100644 --- a/mcs/class/corlib/Test/System.Threading/InterlockedTest.cs +++ b/mcs/class/corlib/Test/System.Threading/InterlockedTest.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using System; using System.Threading; +using System.Runtime.InteropServices; namespace MonoTests.System.Threading { @@ -42,9 +43,19 @@ namespace MonoTests.System.Threading readonly IntPtr iptr_2 = (IntPtr)int32_2; readonly IntPtr iptr_3 = (IntPtr)int32_3; + // The exchange tests are broken on AIX and cause a runtime lockup. + void AssertNotAix() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("AIX"))) + { + Assert.Ignore ("Skipping on AIX/i"); + } + } + [Test] public void TestExchange_Int32 () { + AssertNotAix(); int32 = int32_1; Assert.AreEqual(int32_1, Interlocked.Exchange(ref int32, int32_2)); Assert.AreEqual(int32_2, int32); @@ -53,6 +64,7 @@ namespace MonoTests.System.Threading [Test] public void TestExchange_Flt () { + AssertNotAix(); flt = flt_1; Assert.AreEqual(flt_1, Interlocked.Exchange(ref flt, flt_2)); Assert.AreEqual(flt_2, flt); @@ -61,6 +73,7 @@ namespace MonoTests.System.Threading [Test] public void TestExchange_Obj () { + AssertNotAix(); obj = obj_1; Assert.AreEqual(obj_1, Interlocked.Exchange(ref obj, obj_2)); Assert.AreEqual(obj_2, obj); @@ -69,6 +82,7 @@ namespace MonoTests.System.Threading [Test] public void TestExchange_Int64 () { + AssertNotAix(); int64 = int64_1; Assert.AreEqual(int64_1, Interlocked.Exchange(ref int64, int64_2)); Assert.AreEqual(int64_2, int64); @@ -77,6 +91,7 @@ namespace MonoTests.System.Threading [Test] public void TestExchange_Dbl () { + AssertNotAix(); dbl = dbl_1; Assert.AreEqual(dbl_1, Interlocked.Exchange(ref dbl, dbl_2)); Assert.AreEqual(dbl_2, dbl); @@ -85,6 +100,7 @@ namespace MonoTests.System.Threading [Test] public void TestExchange_Iptr () { + AssertNotAix(); iptr = iptr_1; Assert.AreEqual(iptr_1, Interlocked.Exchange(ref iptr, iptr_2)); Assert.AreEqual(iptr_2, iptr); @@ -93,6 +109,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Int32 () { + AssertNotAix(); int32 = int32_1; Assert.AreEqual(int32_1, Interlocked.CompareExchange(ref int32, int32_2, int32_1)); Assert.AreEqual(int32_2, int32); @@ -101,6 +118,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Flt () { + AssertNotAix(); flt = flt_1; Assert.AreEqual(flt_1, Interlocked.CompareExchange(ref flt, flt_2, flt_1)); Assert.AreEqual(flt_2, flt); @@ -109,6 +127,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Obj () { + AssertNotAix(); obj = obj_1; Assert.AreEqual(obj_1, Interlocked.CompareExchange(ref obj, obj_2, obj_1)); Assert.AreEqual(obj_2, obj); @@ -117,6 +136,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Int64 () { + AssertNotAix(); int64 = int64_1; Assert.AreEqual(int64_1, Interlocked.CompareExchange(ref int64, int64_2, int64_1)); Assert.AreEqual(int64_2, int64); @@ -125,6 +145,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Dbl () { + AssertNotAix(); dbl = dbl_1; Assert.AreEqual(dbl_1, Interlocked.CompareExchange(ref dbl, dbl_2, dbl_1)); Assert.AreEqual(dbl_2, dbl); @@ -133,6 +154,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Iptr () { + AssertNotAix(); iptr = iptr_1; Assert.AreEqual(iptr_1, Interlocked.CompareExchange(ref iptr, iptr_2, iptr_1)); Assert.AreEqual(iptr_2, iptr); @@ -141,6 +163,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Failed_Int32 () { + AssertNotAix(); int32 = int32_1; Assert.AreEqual(int32_1, Interlocked.CompareExchange(ref int32, int32_2, int32_3)); Assert.AreEqual(int32_1, int32); @@ -149,6 +172,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Failed_Flt () { + AssertNotAix(); flt = flt_1; Assert.AreEqual(flt_1, Interlocked.CompareExchange(ref flt, flt_2, flt_3)); Assert.AreEqual(flt_1, flt); @@ -157,6 +181,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Failed_Obj () { + AssertNotAix(); obj = obj_1; Assert.AreEqual(obj_1, Interlocked.CompareExchange(ref obj, obj_2, obj_3)); Assert.AreEqual(obj_1, obj); @@ -165,6 +190,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Failed_Int64 () { + AssertNotAix(); int64 = int64_1; Assert.AreEqual(int64_1, Interlocked.CompareExchange(ref int64, int64_2, int64_3)); Assert.AreEqual(int64_1, int64); @@ -173,6 +199,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Failed_Dbl () { + AssertNotAix(); dbl = dbl_1; Assert.AreEqual(dbl_1, Interlocked.CompareExchange(ref dbl, dbl_2, dbl_3)); Assert.AreEqual(dbl_1, dbl); @@ -181,6 +208,7 @@ namespace MonoTests.System.Threading [Test] public void TestCompareExchange_Failed_Iptr () { + AssertNotAix(); iptr = iptr_1; Assert.AreEqual(iptr_1, Interlocked.CompareExchange(ref iptr, iptr_2, iptr_3)); Assert.AreEqual(iptr_1, iptr); diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index aab80ee99a3..af214218d3e 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -849,7 +849,8 @@ HANDLES(MARSHAL_41, "copy_from_unmanaged_fixed", ves_icall_System_Runtime_Intero HANDLES(MARSHAL_42, "copy_to_unmanaged_fixed", ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged, void, 5, (MonoArray, gint32, gpointer, gint32, gconstpointer)) ICALL_TYPE(RUNTIMEINFO, "System.Runtime.InteropServices.RuntimeInformation", RUNTIMEINFO_1) -HANDLES(RUNTIMEINFO_1, "get_RuntimeArchitecture", ves_icall_System_Runtime_InteropServices_RuntimeInformation_get_RuntimeArchitecture, MonoString, 0, ()) +HANDLES(RUNTIMEINFO_1, "GetOSName", ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetOSName, MonoString, 0, ()) +HANDLES(RUNTIMEINFO_2, "GetRuntimeArchitecture", ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetRuntimeArchitecture, MonoString, 0, ()) #ifndef DISABLE_COM ICALL_TYPE(WINDOWSRUNTIME_UNM, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods", WINDOWSRUNTIME_UNM_0) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 1ae3b6f64ef..d8a37befd77 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -7828,12 +7828,22 @@ ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeH * which use them in different ways for filling in an enum */ MonoStringHandle -ves_icall_System_Runtime_InteropServices_RuntimeInformation_get_RuntimeArchitecture (MonoError *error) +ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetRuntimeArchitecture (MonoError *error) { error_init (error); return mono_string_new_handle (mono_domain_get (), mono_config_get_cpu (), error); } +/* + * used by System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform + */ +MonoStringHandle +ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetOSName (MonoError *error) +{ + error_init (error); + return mono_string_new_handle (mono_domain_get (), mono_config_get_os (), error); +} + int ves_icall_Interop_Sys_DoubleToString(double value, char *format, char *buffer, int bufferLength) { -- 2.11.4.GIT