Merge pull request #1972 from esdrubal/proc_pidpath
authorMarcos Henrich <marcoshenrich@gmail.com>
Fri, 14 Aug 2015 09:08:23 +0000 (10:08 +0100)
committerMarcos Henrich <marcoshenrich@gmail.com>
Fri, 14 Aug 2015 09:08:23 +0000 (10:08 +0100)
[runtime] GetModuleFileNameEx

33 files changed:
configure.ac
mcs/class/Makefile
mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs
mcs/class/Mono.Posix/Test/Mono.Unix.Android/TestHelper.cs [new file with mode: 0644]
mcs/class/Mono.Posix/Test/Mono.Unix.Native/RealTimeSignumTests.cs
mcs/class/Mono.Posix/Test/Mono.Unix/UnixSignalTest.cs
mcs/class/System.Net.Http/monotouch_System.Net.Http.dll.sources [deleted file]
mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.sources [deleted file]
mcs/class/System/System.IO/KeventWatcher.cs
mcs/class/corlib/ReferenceSources/TextInfo.cs
mcs/class/corlib/System.Threading/Monitor.cs
mcs/class/corlib/System/Math.cs [deleted file]
mcs/class/corlib/Test/System.IO.IsolatedStorage/IsolatedStorageFileTest.cs
mcs/class/corlib/Test/System/MathTest.cs
mcs/class/corlib/corlib.dll.sources
mono/metadata/filewatcher.c
mono/metadata/filewatcher.h
mono/metadata/icall-def.h
mono/metadata/sysmath.c
mono/metadata/sysmath.h
mono/metadata/threadpool-ms-io.c
mono/mini/aot-runtime.c
mono/mini/branch-opts.c
mono/mini/method-to-ir.c
mono/mini/mini-exceptions.c
mono/profiler/decode.c
mono/profiler/mono-codeanalyst.c [deleted file]
mono/profiler/proflog.c
mono/profiler/proflog.h
runtime/Makefile.am
scripts/mono-find-provides.in
support/errno.c

index 7191db1858c1080b7a2f7b281fa2d2c1f7b75dd4..13e5d617661f0fb739d78c3355faaaa2a5037b01 100644 (file)
@@ -2362,8 +2362,6 @@ if test "x$ac_cv_truncl" != "xyes"; then
    AC_CHECK_LIB(sunmath, aintl, [ AC_DEFINE(HAVE_AINTL, 1, [Has the 'aintl' function]) LIBS="$LIBS -lsunmath"])
 fi
 
-AC_CHECK_FUNCS(round)
-AC_CHECK_FUNCS(rint)
 AC_CHECK_FUNCS(execvp)
 
 dnl ****************************
@@ -2871,6 +2869,11 @@ if test "x$host" != "x$target"; then
                # Can't use tls, since it depends on the runtime detection of tls offsets
                # in mono-compiler.h
                with_tls=pthread
+               case "$target" in
+               armv7k-*)
+                       AC_DEFINE(TARGET_WATCHOS, 1, [...])
+                       ;;
+               esac            
                ;;
    powerpc64-ps3-linux-gnu)
                TARGET=POWERPC64
@@ -3419,10 +3422,11 @@ case "x$libgc" in
                ;;
 esac
 
-AC_ARG_WITH(profile4_x,[  --with-profile4=yes,no          If you want to install the 4.6 FX (defaults to yes)],                [], [with_profile4_x=yes])
-AC_ARG_WITH(monodroid, [  --with-monodroid=yes,no         If you want to build the MonoDroid assemblies (defaults to no)],     [], [with_monodroid=no])
-AC_ARG_WITH(monotouch, [  --with-monotouch=yes,no         If you want to build the Xamarin.iOS assemblies (defaults to no)],   [], [with_monotouch=no])
-AC_ARG_WITH(xammac,    [  --with-xammac=yes,no            If you want to build the Xamarin.Mac assemblies (defaults to no)],   [], [with_xammac=no])
+AC_ARG_WITH(profile4_x,      [  --with-profile4=yes,no          If you want to install the 4.6 FX (defaults to yes)],                 [], [with_profile4_x=yes])
+AC_ARG_WITH(monodroid,       [  --with-monodroid=yes,no         If you want to build the MonoDroid assemblies (defaults to no)],      [], [with_monodroid=no])
+AC_ARG_WITH(monotouch,       [  --with-monotouch=yes,no         If you want to build the Xamarin.iOS assemblies (defaults to no)],    [], [with_monotouch=no])
+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=no])
+AC_ARG_WITH(xammac,          [  --with-xammac=yes,no            If you want to build the Xamarin.Mac assemblies (defaults to no)],    [], [with_xammac=no])
 
 OPROFILE=no
 AC_ARG_WITH(oprofile,[  --with-oprofile=no,<oprofile install dir>   Enable oprofile support (defaults to no)],[
@@ -3509,6 +3513,7 @@ if test x$cross_compiling = xyes -o x$enable_mcs_build = xno; then
    with_profile4_x=no
    with_monodroid=no
    with_monotouch=no
+   with_monotouch_watch=no
    with_xammac=no
 fi
 
@@ -3531,6 +3536,7 @@ libmono_ldflags="$libmono_ldflags $LIBS"
 AM_CONDITIONAL(INSTALL_4_x, [test "x$with_profile4_x" = xyes])
 AM_CONDITIONAL(INSTALL_MONODROID, [test "x$with_monodroid" != "xno"])
 AM_CONDITIONAL(INSTALL_MONOTOUCH, [test "x$with_monotouch" != "xno"])
+AM_CONDITIONAL(INSTALL_MONOTOUCH_WATCH, [test "x$with_monotouch_watch" != "xno"])
 AM_CONDITIONAL(INSTALL_XAMMAC, [test "x$with_xammac" != "xno"])
 
 AM_CONDITIONAL(MIPS_GCC, test ${TARGET}${ac_cv_prog_gcc} = MIPSyes)
@@ -3945,13 +3951,14 @@ echo "
        LLVM Back End: $enable_llvm (dynamically loaded: $enable_loadedllvm)
 
    Libraries:
-       .NET 4.6:      $with_profile4_x
-       MonoDroid:     $with_monodroid
-       MonoTouch:     $with_monotouch
-       Xamarin.Mac:   $with_xammac
-       JNI support:   $jdk_headers_found
-       libgdiplus:    $libgdiplus_msg
-       zlib:          $zlib_msg
+       .NET 4.6:        $with_profile4_x
+       MonoDroid:       $with_monodroid
+       Xamarin.iOS:     $with_monotouch
+       Xamarin.WatchOS: $with_monotouch_watch
+       Xamarin.Mac:     $with_xammac
+       JNI support:     $jdk_headers_found
+       libgdiplus:      $libgdiplus_msg
+       zlib:            $zlib_msg
        $disabled
 "
 if test x$with_static_mono = xno -a "x$host_win32" != "xyes"; then
index 09aa79c3d88d6caf1774a6b7f6f731dcc9b3e630..3e336f985322c2432cac9a767a64a41f79cdf98b 100644 (file)
@@ -46,6 +46,8 @@ mobile_common_dirs := \
        System.ComponentModel.DataAnnotations \
        System.ComponentModel.Composition.4.5 \
        System.Net \
+       System.Net.Http \
+       System.Net.Http.WebRequest      \
        System.Windows \
        System.Xml.Serialization \
        Mono.CSharp     \
@@ -59,8 +61,6 @@ mobile_static_dirs := \
 mobile_dynamic_dirs := \
        $(mobile_common_dirs)   \
        Mono.CompilerServices.SymbolWriter      \
-       System.Net.Http \
-       System.Net.Http.WebRequest      \
        $(pcl_facade_dirs)
 
 xammac_dirs := \
index 270b0b6aee680cb64332b06638110b58a6eda18b..0f84821b52ee01392b762e7b76723da1306510b2 100644 (file)
@@ -6,5 +6,6 @@ Mono.Unix/UnixMarshalTest.cs
 Mono.Unix/UnixPathTest.cs
 Mono.Unix/UnixSignalTest.cs
 Mono.Unix/UnixUserTest.cs
+Mono.Unix.Android/TestHelper.cs
 Mono.Unix.Native/RealTimeSignumTests.cs
 Mono.Unix.Native/StdlibTest.cs
index ffa329f1b5bf3d5fa7cc75a7a6e93355b118d117..4e2613b127991263f8ba2d31fede7f7da2a99f1f 100644 (file)
@@ -17,10 +17,10 @@ namespace Mono.Unix.Native {
                //
                // Non-generated exports
                //
-
+#if !MONODROID
                [DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
                private static extern int FromRealTimeSignum (Int32 offset, out Int32 rval);
-
+#endif
                // convert a realtime signal to os signal
                public static int FromRealTimeSignum (RealTimeSignum sig)
                {
diff --git a/mcs/class/Mono.Posix/Test/Mono.Unix.Android/TestHelper.cs b/mcs/class/Mono.Posix/Test/Mono.Unix.Android/TestHelper.cs
new file mode 100644 (file)
index 0000000..a7a56a4
--- /dev/null
@@ -0,0 +1,12 @@
+namespace Mono.Unix.Android
+{
+       // Another version of this class is used by the Xamarin.Android test suite
+       // It is here to keep the test code #ifdef free as much as possible
+       public class TestHelper
+       {
+               public static bool CanUseRealTimeSignals ()
+               {
+                       return true;
+               }
+       }
+}
\ No newline at end of file
index 4aea4e8ba60f4db71577c3f9789c4c6333bab39f..f68fe53b8ce70b896dbb603a9530042fddae1885 100644 (file)
@@ -15,6 +15,7 @@ using System;
 using System.Text;
 using System.Threading;
 using Mono.Unix;
+using Mono.Unix.Android;
 using Mono.Unix.Native;
 
 namespace MonoTests.Mono.Unix.Native {
@@ -27,6 +28,8 @@ namespace MonoTests.Mono.Unix.Native {
                [ExpectedException (typeof (ArgumentOutOfRangeException))]
                public void TestRealTimeOutOfRange ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (int.MaxValue);
                }
 
@@ -34,12 +37,16 @@ namespace MonoTests.Mono.Unix.Native {
                [ExpectedException (typeof (ArgumentOutOfRangeException))]
                public void TestRealTimeSignumNegativeOffset ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (-1);
                }
 
                [Test]
                public void TestRTSignalEquality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (0);
                        Assert.That (rts1 == rts2, Is.True);
@@ -49,6 +56,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestRTSignalInequality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (1);
                        Assert.That (rts1 == rts2, Is.False);
@@ -58,6 +67,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestRTSignalGetHashCodeEquality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (0);
                        Assert.That (rts1.GetHashCode (), Is.EqualTo(rts2.GetHashCode ()));
@@ -66,6 +77,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestRTSignalGetHashCodeInequality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (1);
                        Assert.That (rts1.GetHashCode (), Is.Not.EqualTo(rts2.GetHashCode ()));
@@ -74,6 +87,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestIsRTSignalPropertyForRTSignum ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal(new RealTimeSignum (0));
                        Assert.That (signal1.IsRealTimeSignal, Is.True);
                }
@@ -81,6 +96,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestIsRTSignalPropertyForSignum ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
                        Assert.That (signal1.IsRealTimeSignal, Is.False);
                }
index b7b4e6fc695e9539dc22237d55b0b1a45c766ff2..f88defeaff50b92118b6d1f2fec9d742ce00a208 100644 (file)
@@ -15,6 +15,7 @@ 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 {} }
@@ -127,6 +128,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRealTimeCstor ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (0);
                        using (UnixSignal s = new UnixSignal (rts))
                        {
@@ -140,6 +143,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestSignumPropertyThrows ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
                        Signum s = signal1.Signum;
                }
@@ -148,6 +153,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRealTimeSignumProperty ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (0);
                        UnixSignal signal1 = new UnixSignal (rts);
                        Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
@@ -158,6 +165,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRealTimePropertyThrows ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
                        RealTimeSignum s = signal1.RealTimeSignum;
                }
@@ -166,6 +175,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRaiseRTMINSignal ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (0);
                        using (UnixSignal signal = new UnixSignal (rts))
                        {
@@ -180,6 +191,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRaiseRTMINPlusOneSignal ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        /*this number is a guestimate, but it's ok*/
                        for (int i = 1; i < 10; ++i) {
                                RealTimeSignum rts = new RealTimeSignum (i);
@@ -205,6 +218,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestCanRegisterRTSignalMultipleTimes ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        /*this number is a guestimate, but it's ok*/
                        for (int i = 1; i < 10; ++i) {
                                RealTimeSignum rts = new RealTimeSignum (i);
diff --git a/mcs/class/System.Net.Http/monotouch_System.Net.Http.dll.sources b/mcs/class/System.Net.Http/monotouch_System.Net.Http.dll.sources
deleted file mode 100644 (file)
index b40b2a1..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-../../build/common/Consts.cs
-Assembly/AssemblyInfo.cs
-System.Net.Http/ByteArrayContent.cs
-System.Net.Http/ClientCertificateOption.cs
-System.Net.Http/DelegatingHandler.cs
-System.Net.Http/FormUrlEncodedContent.cs
-System.Net.Http/HttpClient.cs
-System.Net.Http/HttpClientHandler.cs
-System.Net.Http/HttpCompletionOption.cs
-System.Net.Http/HttpContent.cs
-System.Net.Http/HttpMessageHandler.cs
-System.Net.Http/HttpMessageInvoker.cs
-System.Net.Http/HttpMethod.cs
-System.Net.Http/HttpRequestException.cs
-System.Net.Http/HttpRequestMessage.cs
-System.Net.Http/HttpResponseMessage.cs
-System.Net.Http/MessageProcessingHandler.cs
-System.Net.Http/MultipartContent.cs
-System.Net.Http/MultipartFormDataContent.cs
-System.Net.Http/StreamContent.cs
-System.Net.Http/StringContent.cs
-System.Net.Http.Headers/AuthenticationHeaderValue.cs
-System.Net.Http.Headers/CacheControlHeaderValue.cs
-System.Net.Http.Headers/CollectionExtensions.cs
-System.Net.Http.Headers/CollectionParser.cs
-System.Net.Http.Headers/ContentDispositionHeaderValue.cs
-System.Net.Http.Headers/ContentRangeHeaderValue.cs
-System.Net.Http.Headers/EntityTagHeaderValue.cs
-System.Net.Http.Headers/HashCodeCalculator.cs
-System.Net.Http.Headers/HeaderInfo.cs
-System.Net.Http.Headers/HttpContentHeaders.cs
-System.Net.Http.Headers/HttpHeaderKind.cs
-System.Net.Http.Headers/HttpHeaders.cs
-System.Net.Http.Headers/HttpHeaderValueCollection.cs
-System.Net.Http.Headers/HttpRequestHeaders.cs
-System.Net.Http.Headers/HttpResponseHeaders.cs
-System.Net.Http.Headers/Lexer.cs
-System.Net.Http.Headers/MediaTypeHeaderValue.cs
-System.Net.Http.Headers/MediaTypeWithQualityHeaderValue.cs
-System.Net.Http.Headers/NameValueHeaderValue.cs
-System.Net.Http.Headers/NameValueWithParametersHeaderValue.cs
-System.Net.Http.Headers/Parser.cs
-System.Net.Http.Headers/ProductHeaderValue.cs
-System.Net.Http.Headers/ProductInfoHeaderValue.cs
-System.Net.Http.Headers/QualityValue.cs
-System.Net.Http.Headers/RangeConditionHeaderValue.cs
-System.Net.Http.Headers/RangeHeaderValue.cs
-System.Net.Http.Headers/RangeItemHeaderValue.cs
-System.Net.Http.Headers/RetryConditionHeaderValue.cs
-System.Net.Http.Headers/StringWithQualityHeaderValue.cs
-System.Net.Http.Headers/TransferCodingHeaderValue.cs
-System.Net.Http.Headers/TransferCodingWithQualityHeaderValue.cs
-System.Net.Http.Headers/ViaHeaderValue.cs
-System.Net.Http.Headers/WarningHeaderValue.cs
\ No newline at end of file
diff --git a/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.sources b/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.sources
deleted file mode 100644 (file)
index 685ab03..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include monotouch_System.Net.Http.dll.sources
\ No newline at end of file
index 27f61b35d0ea775478f504f0b288e67620fa7559..0d2e39ee02baddcd7c5f4743b3c8087a6af1cdc6 100644 (file)
@@ -355,7 +355,21 @@ namespace System.IO {
                        while (!requestStop) {
                                var changes = CreateChangeList (ref newFds);
 
-                               int numEvents = kevent_notimeout (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, IntPtr.Zero);
+                               // We are calling an icall, so have to marshal manually
+                               // Marshal in
+                               int ksize = Marshal.SizeOf<kevent> ();
+                               var changesNative = Marshal.AllocHGlobal (ksize * changes.Length);
+                               for (int i = 0; i < changes.Length; ++i)
+                                       Marshal.StructureToPtr (changes [i], changesNative + (i * ksize), false);
+                               var eventBufferNative = Marshal.AllocHGlobal (ksize * eventBuffer.Length);
+
+                               int numEvents = kevent_notimeout (ref conn, changesNative, changes.Length, eventBufferNative, eventBuffer.Length);
+
+                               // Marshal out
+                               Marshal.FreeHGlobal (changesNative);
+                               for (int i = 0; i < numEvents; ++i)
+                                       eventBuffer [i] = Marshal.PtrToStructure<kevent> (eventBufferNative + (i * ksize));
+                               Marshal.FreeHGlobal (eventBufferNative);
 
                                if (numEvents == -1) {
                                        // Stop () signals us to stop by closing the connection
@@ -367,7 +381,6 @@ namespace System.IO {
 
                                        continue;
                                }
-
                                retries = 0;
 
                                for (var i = 0; i < numEvents; i++) {
@@ -658,8 +671,8 @@ namespace System.IO {
                [DllImport ("libc")]
                extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time);
 
-               [DllImport ("libc", EntryPoint="kevent")]
-               extern static int kevent_notimeout (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, IntPtr ptr);
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static int kevent_notimeout (ref int kq, IntPtr ev, int nchanges, IntPtr evtlist, int nevents);
        }
 
        class KeventWatcher : IFileWatcher
index 53538b65e8d54c5a002f652cf4b7249847ecc562..5811cdc8337644fa162986abd2fef1e79988e376 100644 (file)
@@ -4,14 +4,6 @@ namespace System.Globalization
 {
        partial class TextInfo
        {
-               unsafe static ushort *to_lower_data_low;
-               unsafe static ushort *to_lower_data_high;
-               unsafe static ushort *to_upper_data_low;
-               unsafe static ushort *to_upper_data_high;
-
-               [MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
-               unsafe static extern void GetDataTablePointersLite (out ushort *to_lower_data_low, out ushort *to_lower_data_high, out ushort *to_upper_data_low, out ushort *to_upper_data_high);
-
                unsafe string ToUpperInternal (string str)
                {
                        if (str.Length == 0)
index 5f00b0a1488576cb5dd1989ff4725207e9505b2b..c5cda6920d2edc3729e325bd3228629350ef94ae 100644 (file)
@@ -195,6 +195,8 @@ namespace System.Threading
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static void enter_with_atomic_var (object obj, ref bool lockTaken);
 
+               // Can't make this an icall since it has the same name as the other Enter method
+               [MethodImpl(MethodImplOptions.AggressiveInlining)]
                public static void Enter (object obj, ref bool lockTaken)
                {
                        enter_with_atomic_var (obj, ref lockTaken);
diff --git a/mcs/class/corlib/System/Math.cs b/mcs/class/corlib/System/Math.cs
deleted file mode 100644 (file)
index 3ba4b62..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-//
-// System.Math.cs
-//
-// Authors:
-//   Bob Smith (bob@thestuff.net)
-//   Dan Lewis (dihlewis@yahoo.co.uk)
-//   Pedro Martínez Juliá (yoros@wanadoo.es)
-//   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-// (C) 2001 Bob Smith.  http://www.thestuff.net
-// Copyright (C) 2003 Pedro Martínez Juliá <yoros@wanadoo.es>
-// Copyright (C) 2004 Novell (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Runtime.CompilerServices;
-using System.Runtime.ConstrainedExecution;
-
-namespace System
-{
-       public static class Math
-       {
-               public const double E = 2.7182818284590452354;
-               public const double PI = 3.14159265358979323846;
-
-               public static decimal Abs (decimal value)
-               {
-                       return (value < 0)? -value: value;
-               }
-
-               public static double Abs (double value)
-               {
-                       return (value < 0)? -value: value;
-               }
-
-               public static float Abs (float value)
-               {
-                       return (value < 0)? -value: value;
-               }
-
-               public static int Abs (int value)
-               {
-                       if (value == Int32.MinValue)
-                               throw new OverflowException (Locale.GetText ("Value is too small."));
-                       return (value < 0)? -value: value;
-               }
-
-               public static long Abs (long value)
-               {
-                       if (value == Int64.MinValue)
-                               throw new OverflowException (Locale.GetText ("Value is too small."));
-                       return (value < 0)? -value: value;
-               }
-
-               [CLSCompliant (false)]
-               public static sbyte Abs (sbyte value)
-               {
-                       if (value == SByte.MinValue)
-                               throw new OverflowException (Locale.GetText ("Value is too small."));
-                       return (sbyte)((value < 0)? -value: value);
-               }
-
-               public static short Abs (short value)
-               {
-                       if (value == Int16.MinValue)
-                               throw new OverflowException (Locale.GetText ("Value is too small."));
-                       return (short)((value < 0)? -value: value);
-               }
-
-               public static decimal Ceiling (decimal d)
-               {
-                       decimal result = Floor(d);
-                       if (result != d) {
-                               result++;
-                       }
-                       return result;
-               }
-
-               public static double Ceiling (double a)
-               {
-                       double result = Floor(a);
-                       if (result != a) {
-                               result++;
-                       }
-                       return result;
-               }
-
-               // The following methods are defined in ECMA specs but they are
-               // not implemented in MS.NET. However, they are in MS.NET 1.1
-
-               public static long BigMul (int a, int b)
-               {
-                       return ((long)a * (long)b);
-               }
-
-               public static int DivRem (int a, int b, out int result)
-               {
-                       result = (a % b);
-                       return (int)(a / b);
-               }
-
-               public static long DivRem (long a, long b, out long result)
-               {
-                       result = (a % b);
-                       return (long)(a / b);
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Floor (double d);
-
-               public static double IEEERemainder (double x, double y)
-               {
-                       double r;
-                       if (y == 0)
-                               return Double.NaN;
-                       r = x - (y * Math.Round(x/y));
-                       if (r != 0)
-                               return r;
-                       /* Int64BitsToDouble is not endian-aware, but that is fine here */
-                       return (x > 0) ? 0: (BitConverter.Int64BitsToDouble (Int64.MinValue));
-               }
-
-               public static double Log (double a, double newBase)
-               {
-                       if (newBase == 1.0)
-                               return Double.NaN;
-                       double result = Log(a) / Log(newBase);
-                       return (result == -0)? 0: result;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static byte Max (byte val1, byte val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static decimal Max (decimal val1, decimal val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static double Max (double val1, double val2)
-               {
-                       if (Double.IsNaN (val1) || Double.IsNaN (val2)) {
-                               return Double.NaN;
-                       }
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static float Max (float val1, float val2)
-               {
-                       if (Single.IsNaN (val1) || Single.IsNaN (val2)) {
-                               return Single.NaN;
-                       }
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static int Max (int val1, int val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static long Max (long val1, long val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static sbyte Max (sbyte val1, sbyte val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static short Max (short val1, short val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static uint Max (uint val1, uint val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static ulong Max (ulong val1, ulong val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static ushort Max (ushort val1, ushort val2)
-               {
-                       return (val1 > val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static byte Min (byte val1, byte val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static decimal Min (decimal val1, decimal val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static double Min (double val1, double val2)
-               {
-                       if (Double.IsNaN (val1) || Double.IsNaN (val2)) {
-                               return Double.NaN;
-                       }
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static float Min (float val1, float val2)
-               {
-                       if (Single.IsNaN (val1) || Single.IsNaN (val2)) {
-                               return Single.NaN;
-                       }
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static int Min (int val1, int val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static long Min (long val1, long val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static sbyte Min (sbyte val1, sbyte val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public static short Min (short val1, short val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static uint Min (uint val1, uint val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static ulong Min (ulong val1, ulong val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               [CLSCompliant (false)]
-               public static ushort Min (ushort val1, ushort val2)
-               {
-                       return (val1 < val2)? val1: val2;
-               }
-
-               public static decimal Round (decimal d)
-               {
-                       // Just call Decimal.Round(d, 0); when it rounds well.
-                       decimal int_part = Decimal.Floor(d);
-                       decimal dec_part = d - int_part;
-                       if (((dec_part == 0.5M) &&
-                               ((2.0M * ((int_part / 2.0M) -
-                               Decimal.Floor(int_part / 2.0M))) != 0.0M)) ||
-                               (dec_part > 0.5M)) {
-                               int_part++;
-                       }
-                       return int_part;
-               }
-
-               public static decimal Round (decimal d, int decimals)
-               {
-                       return Decimal.Round (d, decimals);
-               }
-
-               public static decimal Round (decimal d, MidpointRounding mode)
-               {
-                       if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
-                               throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
-
-                       if (mode == MidpointRounding.ToEven)
-                               return Round (d);
-                       else
-                               return RoundAwayFromZero (d);
-               }
-
-               static decimal RoundAwayFromZero (decimal d)
-               {
-                       decimal int_part = Decimal.Floor(d);
-                       decimal dec_part = d - int_part;
-                       if (int_part >= 0 && dec_part >= 0.5M)
-                               int_part++;
-                       else if (int_part < 0 && dec_part > 0.5M)
-                               int_part++;
-                       return int_part;
-               }
-
-               public static decimal Round (decimal d, int decimals, MidpointRounding mode)
-               {
-                       return Decimal.Round (d, decimals, mode);
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Round (double a);
-
-               public static double Round (double value, int digits)
-               {
-                       if (digits < 0 || digits > 15)
-                               throw new ArgumentOutOfRangeException (Locale.GetText ("Value is too small or too big."));
-                       if (digits == 0)
-                               return Round (value);
-
-                       return Round2(value, digits, false);
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern static double Round2 (double value, int digits, bool away_from_zero);
-
-
-               public static double Round (double value, MidpointRounding mode)
-               {
-                       if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
-                               throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
-
-                       if (mode == MidpointRounding.ToEven)
-                               return Round (value);
-                       if (value > 0)
-                               return Floor (value + 0.5);
-                       else
-                               return Ceiling (value - 0.5);
-               }
-
-               public static double Round (double value, int digits, MidpointRounding mode)
-               {
-                       if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
-                               throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
-                       if (digits == 0)
-                               return Round (value, mode);
-
-                       if (mode == MidpointRounding.ToEven)
-                               return Round (value, digits);
-                       else
-                               return Round2 (value, digits, true);
-               }
-               
-               public static double Truncate (double d)
-               {
-                       if (d > 0D)
-                               return Floor (d);
-                       else if (d < 0D)
-                               return Ceiling (d);
-                       else
-                               return d;
-               }
-
-               public static decimal Truncate (decimal d)
-               {
-                       return Decimal.Truncate (d);
-               }
-
-               public static decimal Floor (Decimal d)
-               {
-                       return Decimal.Floor (d);
-               }
-
-               public static int Sign (decimal value)
-               {
-                       if (value > 0) return 1;
-                       return (value == 0)? 0: -1;
-               }
-
-               public static int Sign (double value)
-               {
-                       if (Double.IsNaN (value))
-                               throw new ArithmeticException ("NAN");
-                       if (value > 0) return 1;
-                       return (value == 0)? 0: -1;
-               }
-
-               public static int Sign (float value)
-               {
-                       if (Single.IsNaN (value))
-                               throw new ArithmeticException ("NAN");
-                       if (value > 0) return 1;
-                       return (value == 0)? 0: -1;
-               }
-
-               public static int Sign (int value)
-               {
-                       if (value > 0) return 1;
-                       return (value == 0)? 0: -1;
-               }
-
-               public static int Sign (long value)
-               {
-                       if (value > 0) return 1;
-                       return (value == 0)? 0: -1;
-               }
-
-               [CLSCompliant (false)]
-               public static int Sign (sbyte value)
-               {
-                       if (value > 0) return 1;
-                       return (value == 0)? 0: -1;
-               }
-
-               public static int Sign (short value)
-               {
-                       if (value > 0) return 1;
-                       return (value == 0)? 0: -1;
-               }
-
-               // internal calls
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Sin (double a);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Cos (double d);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Tan (double a);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Sinh (double value);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Cosh (double value);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Tanh (double value);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Acos (double d);
-               
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Asin (double d);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Atan (double d);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Atan2 (double y, double x);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Exp (double d);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Log (double d);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Log10 (double d);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static double Pow (double x, double y);
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-               public extern static double Sqrt (double d);
-       }
-}
index 459974cdee4510253d0c38f84162660fd6ca688e..66eb27ed32407833e14b69f9fc6cb357b4f3d7ab 100644 (file)
@@ -1034,7 +1034,6 @@ namespace MonoTests.System.IO.IsolatedStorageTest {
                                isf.MoveFile ("  ", "file-new-new");
                                Assert.Fail ("#Exc2");
                        } catch (ArgumentException e) {
-                               Console.WriteLine (e);
                        }
 
                        try {
index 355b3960b01c10e864abe021e2e19faa9d2d5c77..ba965817e0c746e43ee20bc0315c85a70fc0d3b9 100644 (file)
@@ -405,7 +405,7 @@ namespace MonoTests.System
                public void TestIEEERemainder ()
                {
                        double a = Math.IEEERemainder (y, x);
-                       double b = 0.0050000000000007816;
+                       double b = 0.0050000000000010592;
 
                        Assert.IsTrue ((Math.Abs (a - b) <= double_epsilon), a.ToString ("G99")
                                + " != " + b.ToString ("G99"));
@@ -456,7 +456,8 @@ namespace MonoTests.System
                        // MS docs say this should be PositiveInfinity
                        Assert.IsTrue (Math.Log (0, y) == double.NegativeInfinity);
                        Assert.IsTrue (Math.Log (double.PositiveInfinity, y) == double.PositiveInfinity);
-                       Assert.IsTrue (Math.Log (x, double.PositiveInfinity) == 0);
+
+                       Assert.IsTrue (Double.IsNaN (Math.Log (x, double.PositiveInfinity)));
                }
 
                [Test]
@@ -488,82 +489,109 @@ namespace MonoTests.System
                        //
                        // when using double_epsilon. Precision differs between different ARM CPUs, so we
                        // will just use a more conservative value
-                       precision = 0.000001;
+                       precision = double_epsilon * 10;
 #else
                        precision = double_epsilon;
 #endif
-                       try {
-                               double a = Math.Pow (y, x);
-                               double b = 1.363609446060212;
-
-                               Assert.IsTrue ((Math.Abs (a - b) <= precision), a.ToString ("G99") + " != " + b.ToString ("G99"));
-                               iTest++;
-                               Assert.IsTrue (double.IsNaN (Math.Pow (y, double.NaN)));
-                               iTest++;
-                               Assert.IsTrue (double.IsNaN (Math.Pow (double.NaN, x)));
-                               iTest++;
-                               Assert.IsTrue (double.IsNegativeInfinity (Math.Pow (double.NegativeInfinity, 1)),
-                                       "Math.Pow(double.NegativeInfinity, 1) should be NegativeInfinity");
-                               iTest++;
-                               Assert.IsTrue (double.IsPositiveInfinity (Math.Pow (double.NegativeInfinity, 2)),
-                                       "Math.Pow(double.NegativeInfinity, 2) should be PositiveInfinity");
 
-                               // MS docs say this should be 0
-                               iTest++;
-                               Assert.IsTrue (double.IsNaN (Math.Pow (1, double.NegativeInfinity)));
-                               iTest++;
-                               Assert.AreEqual ((double) 0, Math.Pow (double.PositiveInfinity, double.NegativeInfinity),
-                                       "Math.Pow(double.PositiveInfinity, double.NegativeInfinity)");
-                               iTest++;
-                               Assert.IsTrue (double.IsPositiveInfinity (Math.Pow (double.PositiveInfinity, 1)),
-                                       "Math.Pow(double.PositiveInfinity, 1) should be PositiveInfinity");
-
-                               // MS docs say this should be PositiveInfinity
-                               iTest++;
-                               Assert.IsTrue (double.IsNaN (Math.Pow (1, double.PositiveInfinity)),
-                                       "Math.Pow(1, double.PositiveInfinity) should be NaN");
-
-                               iTest++;
-                               Assert.IsTrue (Double.IsNaN (Math.Pow (1, Double.NaN)),
-                                       "Math.Pow(1, NaN) should be NaN");
-                               iTest++;
-                               Assert.IsTrue (Double.IsNaN (Math.Pow (Double.NaN, 0)),
-                                       "Math.Pow(NaN, 0) should be NaN");
-                               iTest++;
-                               Assert.IsTrue (1.0 == Math.Pow (-1, Double.MaxValue),
-                                       "Math.Pow(-1, MaxValue) should be 1.0");
-
-                               iTest++;
-                               Assert.IsTrue (1.0 == Math.Pow (-1, Double.MinValue),
-                                       "Math.Pow(-1, MinValue) should be 1.0");
-
-                               iTest++;
-                               Assert.IsTrue (Double.IsPositiveInfinity (Math.Pow (Double.MinValue,
-                                       Double.MaxValue)), "Math.Pow(MinValue, MaxValue) should be +Infinity");
-
-                               iTest++;
-                               Assert.IsTrue (0.0 == Math.Pow (Double.MinValue, Double.MinValue),
-                                       "Math.Pow(MinValue, MinValue) should be 0.0");
-
-                               //
-                               // The following bugs were present because we tried to outsmart the C Pow:
-                               //
-                               double infinity = Double.PositiveInfinity;
-                               Assert.IsTrue (Math.Pow (0.5, infinity) == 0.0,
-                                       "Math.Pow(0.5, Infinity) == 0.0");
-                               Assert.IsTrue (Math.Pow (0.5, -infinity) == infinity,
-                                       "Math.Pow(0.5, -Infinity) == Infinity");
-                               Assert.IsTrue (Math.Pow (2, infinity) == infinity,
-                                       "Math.Pow(2, Infinity) == Infinity");
-                               Assert.IsTrue (Math.Pow (2, -infinity) == 0.0,
-                                       "Math.Pow(2, -Infinity) == 0");
-                               Assert.IsTrue (Math.Pow (infinity, 0) == 1.0,
-                                       "Math.Pow(Infinity, 0) == 1.0");
-                               Assert.IsTrue (Math.Pow (-infinity, 0) == 1.0,
-                                       "Math.Pow(-Infinity, 0) == 1.0");
-                       } catch (Exception e) {
-                               Assert.Fail ("Unexpected exception at iTest=" + iTest + ". e=" + e);
-                       }
+                       /* documentation cases : https://msdn.microsoft.com/en-us/library/system.math.pow%28v=vs.110%29.aspx */
+
+                       /* x or y = NaN -> NaN */
+                       Assert.IsNaN (Math.Pow (             double.NaN,              double.NaN), "#1");
+                       Assert.IsNaN (Math.Pow (             double.NaN, double.NegativeInfinity), "#2");
+                       Assert.IsNaN (Math.Pow (             double.NaN,                      -2), "#2");
+                       Assert.IsNaN (Math.Pow (             double.NaN,                      -1), "#3");
+                       Assert.IsNaN (Math.Pow (             double.NaN,                       0), "#4");
+                       Assert.IsNaN (Math.Pow (             double.NaN,                       1), "#5");
+                       Assert.IsNaN (Math.Pow (             double.NaN,                       2), "#6");
+                       Assert.IsNaN (Math.Pow (             double.NaN, double.PositiveInfinity), "#7");
+                       Assert.IsNaN (Math.Pow (double.NegativeInfinity,              double.NaN), "#8");
+                       Assert.IsNaN (Math.Pow (                     -2,              double.NaN), "#9");
+                       Assert.IsNaN (Math.Pow (                     -1,              double.NaN), "#10");
+                       Assert.IsNaN (Math.Pow (                      0,              double.NaN), "#11");
+                       Assert.IsNaN (Math.Pow (                      1,              double.NaN), "#12");
+                       Assert.IsNaN (Math.Pow (                      2,              double.NaN), "#13");
+                       Assert.IsNaN (Math.Pow (double.PositiveInfinity,              double.NaN), "#14");
+
+                       /* x = Any value except NaN; y = 0 -> 1 */
+                       Assert.AreEqual ((double) 1, Math.Pow (2, 0), "#15");
+
+                       /* x = NegativeInfinity; y < 0 -> 0 */
+                       Assert.AreEqual ((double) 0, Math.Pow (double.NegativeInfinity, -2), "#16");
+
+                       /* x = NegativeInfinity; y is a positive odd integer -> NegativeInfinity */
+                       Assert.AreEqual (double.NegativeInfinity, Math.Pow (double.NegativeInfinity, 3), "#17");
+
+                       /* x = NegativeInfinity; y is positive but not an odd integer -> PositiveInfinity */
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (double.NegativeInfinity, 2), "#18");
+
+                       /* x < 0 but not NegativeInfinity; y is not an integer, NegativeInfinity, or PositiveInfinity -> NaN */
+                       Assert.IsNaN (Math.Pow (-1, 2.5), "#19");
+
+                       /* x = -1; y = NegativeInfinity or PositiveInfinity -> NaN */
+                       Assert.IsNaN (Math.Pow (-1, double.PositiveInfinity), "#20");
+                       Assert.IsNaN (Math.Pow (-1, double.NegativeInfinity), "#21");
+
+                       /* -1 < x < 1; y = NegativeInfinity -> PositiveInfinity */
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (-0.5, double.NegativeInfinity), "#22");
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (+0.5, double.NegativeInfinity), "#23");
+
+                       /* -1 < x < 1; y = PositiveInfinity -> 0 */
+                       Assert.AreEqual ((double) 0, Math.Pow (-0.5, double.PositiveInfinity), "#24");
+                       Assert.AreEqual ((double) 0, Math.Pow (+0.5, double.PositiveInfinity), "#25");
+
+                       /* x < -1 or x > 1; y = NegativeInfinity -> 0 */
+                       Assert.AreEqual ((double) 0, Math.Pow (-2, double.NegativeInfinity), "#26");
+                       Assert.AreEqual ((double) 0, Math.Pow (+2, double.NegativeInfinity), "#27");
+
+                       /* x < -1 or x > 1; y = PositiveInfinity -> PositiveInfinity */
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (-2, double.PositiveInfinity), "#28");
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (+2, double.PositiveInfinity), "#29");
+
+                       /* x = 0; y < 0 -> PositiveInfinity */
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (0, -2), "#30");
+
+                       /* x = 0; y > 0 -> PositiveInfinity */
+                       Assert.AreEqual ((double) 0, Math.Pow (0, +2), "#31");
+
+                       /* x = 1; y is any value except NaN -> 1 */
+                       Assert.AreEqual ((double) 1, Math.Pow (1, double.NegativeInfinity), "#32");
+                       Assert.AreEqual ((double) 1, Math.Pow (1,                      -2), "#33");
+                       Assert.AreEqual ((double) 1, Math.Pow (1,                       0), "#34");
+                       Assert.AreEqual ((double) 1, Math.Pow (1,                      +2), "#35");
+                       Assert.AreEqual ((double) 1, Math.Pow (1, double.PositiveInfinity), "#36");
+
+                       /* x = PositiveInfinity; y < 0 -> 0 */
+                       Assert.AreEqual ((double) 0, Math.Pow (double.PositiveInfinity, -1), "#37");
+                       Assert.AreEqual ((double) 0, Math.Pow (double.PositiveInfinity, -2), "#38");
+
+                       /* x = PositiveInfinity; y > 0 -> PositiveInfinity */
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (double.PositiveInfinity, 1), "#39");
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (double.PositiveInfinity, 2), "#40");
+
+                       /* other cases */
+
+                       double a = Math.Pow (y, x);
+                       double b = 1.363609446060212;
+
+                       Assert.IsTrue (Math.Abs (a - b) <= precision, "#41 " + a.ToString ("G99") + " != " + b.ToString ("G99") + " +/- " + precision.ToString ("G99"));
+                       Assert.AreEqual (double.NegativeInfinity, Math.Pow (double.NegativeInfinity, 1), "#42");
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (double.NegativeInfinity, 2), "#43");
+
+                       Assert.AreEqual (Math.Pow (double.PositiveInfinity, double.NegativeInfinity), (double) 0, "#44");
+
+                       Assert.AreEqual ((double) 1, Math.Pow (-1, Double.MaxValue), "#45");
+                       Assert.AreEqual ((double) 1, Math.Pow (-1, Double.MinValue), "#46");
+                       Assert.AreEqual ((double) 0, Math.Pow (Double.MinValue, Double.MinValue), "#47");
+                       Assert.AreEqual (double.PositiveInfinity, Math.Pow (Double.MinValue, Double.MaxValue), "#48");
+
+                       double infinity = double.PositiveInfinity;
+                       Assert.AreEqual ((double) 0, Math.Pow (      0.5,  infinity), "#49");
+                       Assert.AreEqual (  infinity, Math.Pow (      0.5, -infinity), "#50");
+                       Assert.AreEqual (  infinity, Math.Pow (        2,  infinity), "#51");
+                       Assert.AreEqual ((double) 0, Math.Pow (        2, -infinity), "#52");
+                       Assert.AreEqual ((double) 1, Math.Pow ( infinity,         0), "#53");
+                       Assert.AreEqual ((double) 1, Math.Pow (-infinity,         0), "#54");
                }
 
                [Test]
index 961c6928149290423fac42911fc9ce51e50093b4..7af21cc117bf581d15584d8654d68b906d2ce25c 100644 (file)
@@ -110,7 +110,6 @@ System/IConsoleDriver.cs
 System/IntPtr.cs
 System/KnownTerminals.cs
 System/MarshalByRefObject.cs
-System/Math.cs
 System/MonoAsyncCall.cs
 System/MonoCQItem.cs
 System/MonoCustomAttrs.cs
@@ -1000,6 +999,7 @@ ReferenceSources/SecurityContext.cs
 ../../../external/referencesource/mscorlib/system/iserviceobjectprovider.cs
 ../../../external/referencesource/mscorlib/system/invalidtimezoneexception.cs
 ../../../external/referencesource/mscorlib/system/Lazy.cs
+../../../external/referencesource/mscorlib/system/math.cs
 ../../../external/referencesource/mscorlib/system/memberaccessexception.cs
 ../../../external/referencesource/mscorlib/system/methodaccessexception.cs
 ../../../external/referencesource/mscorlib/system/midpointrounding.cs
index 664b28a05275b7bf3e68ec29e248736ca4c8ba37..def11d9856d8be929b37c1fc92f0c48651ca4dd4 100644 (file)
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_EVENT_H
+#include <sys/event.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/filewatcher.h>
@@ -188,3 +198,55 @@ ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor)
        return inotify_rm_watch (fd, watch_descriptor);
 }
 #endif
+
+#if HAVE_KQUEUE
+
+static void
+interrupt_kevent (gpointer data)
+{
+       int *kq_ptr = data;
+
+       /* Interrupt the kevent () call by closing the fd */
+       close (*kq_ptr);
+       /* Signal to managed code that the fd is closed */
+       *kq_ptr = -1;
+}
+
+/*
+ * ves_icall_System_IO_KqueueMonitor_kevent_notimeout:
+ *
+ *   Call kevent (), while handling runtime interruptions.
+ */
+int
+ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
+{
+       int res;
+       gboolean interrupted;
+
+       mono_thread_info_install_interrupt (interrupt_kevent, kq_ptr, &interrupted);
+       if (interrupted) {
+               close (*kq_ptr);
+               *kq_ptr = -1;
+               return -1;
+       }
+
+       MONO_PREPARE_BLOCKING;
+       res = kevent (*kq_ptr, changelist, nchanges, eventlist, nevents, NULL);
+       MONO_FINISH_BLOCKING;
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+
+       return res;
+}
+
+#else
+
+int
+ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
+{
+       g_assert_not_reached ();
+       return -1;
+}
+
+#endif /* #if HAVE_KQUEUE */
+
index c57be128325b0e1f203cdaf325177806779463d3..605fd0e9ac2503d70c8eb2051e4bf7043adf4846 100644 (file)
@@ -32,6 +32,8 @@ int ves_icall_System_IO_InotifyWatcher_GetInotifyInstance (void);
 int ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *directory, gint32 mask);
 int ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor);
 
+int ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq, gpointer changelist, int nchanges, gpointer eventlist, int nevents);
+
 G_END_DECLS
 
 #endif
index 787e5d84b3687a3175387a9ce490486acf168310..429ce31f5f537a0d557e95c6196059aa9b1e57fb 100644 (file)
@@ -306,6 +306,9 @@ ICALL(INOW_1, "AddWatch", ves_icall_System_IO_InotifyWatcher_AddWatch)
 ICALL(INOW_2, "GetInotifyInstance", ves_icall_System_IO_InotifyWatcher_GetInotifyInstance)
 ICALL(INOW_3, "RemoveWatch", ves_icall_System_IO_InotifyWatcher_RemoveWatch)
 
+ICALL_TYPE(KQUEM, "System.IO.KqueueMonitor", KQUEM_1)
+ICALL(KQUEM_1, "kevent_notimeout", ves_icall_System_IO_KqueueMonitor_kevent_notimeout)
+
 ICALL_TYPE(MMAPIMPL, "System.IO.MemoryMappedFiles.MemoryMapImpl", MMAPIMPL_1)
 ICALL(MMAPIMPL_1, "CloseMapping", mono_mmap_close)
 ICALL(MMAPIMPL_2, "ConfigureHandleInheritability", mono_mmap_configure_inheritability)
@@ -366,11 +369,14 @@ ICALL(MONOIO_33, "get_VolumeSeparatorChar", ves_icall_System_IO_MonoIO_get_Volum
 ICALL_TYPE(IOPATH, "System.IO.Path", IOPATH_1)
 ICALL(IOPATH_1, "get_temp_path", ves_icall_System_IO_get_temp_path)
 
-ICALL_TYPE(MATH, "System.Math", MATH_1)
+ICALL_TYPE(MATH, "System.Math", MATH_19)
+ICALL(MATH_19, "Abs(double)", ves_icall_System_Math_Abs_double)
+ICALL(MATH_20, "Abs(single)", ves_icall_System_Math_Abs_single)
 ICALL(MATH_1, "Acos", ves_icall_System_Math_Acos)
 ICALL(MATH_2, "Asin", ves_icall_System_Math_Asin)
 ICALL(MATH_3, "Atan", ves_icall_System_Math_Atan)
 ICALL(MATH_4, "Atan2", ves_icall_System_Math_Atan2)
+ICALL(MATH_21, "Ceiling", ves_icall_System_Math_Ceiling)
 ICALL(MATH_5, "Cos", ves_icall_System_Math_Cos)
 ICALL(MATH_6, "Cosh", ves_icall_System_Math_Cosh)
 ICALL(MATH_7, "Exp", ves_icall_System_Math_Exp)
@@ -379,9 +385,9 @@ ICALL(MATH_9, "Log", ves_icall_System_Math_Log)
 ICALL(MATH_10, "Log10", ves_icall_System_Math_Log10)
 ICALL(MATH_11, "Pow", ves_icall_System_Math_Pow)
 ICALL(MATH_12, "Round", ves_icall_System_Math_Round)
-ICALL(MATH_13, "Round2", ves_icall_System_Math_Round2)
 ICALL(MATH_14, "Sin", ves_icall_System_Math_Sin)
 ICALL(MATH_15, "Sinh", ves_icall_System_Math_Sinh)
+ICALL(MATH_22, "SplitFractionDouble", ves_icall_System_Math_SplitFractionDouble)
 ICALL(MATH_16, "Sqrt", ves_icall_System_Math_Sqrt)
 ICALL(MATH_17, "Tan", ves_icall_System_Math_Tan)
 ICALL(MATH_18, "Tanh", ves_icall_System_Math_Tanh)
index de24fcb0fa51d5c40bc1b613658527350e7653ed..47cbcfd599f3281305c628b8e82f994c2dd3bb02 100644 (file)
  *
  * Author:
  *     Mono Project (http://www.mono-project.com)
+ *     Ludovic Henry (ludovic@xamarin.com)
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2015 Xamarin, Inc (https://www.xamarin.com)
  */
+
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// Files:
+//  - src/classlibnative/float/floatnative.cpp
+//  - src/pal/src/cruntime/floatnative.cpp
+//
+// Ported from C++ to C and adjusted to Mono runtime
+
 #define __USE_ISOC99
+
 #include <math.h>
 #include <mono/metadata/sysmath.h>
-#include <mono/metadata/exception.h>
-
-#ifndef NAN
-# if G_BYTE_ORDER == G_BIG_ENDIAN
-#  define __nan_bytes           { 0x7f, 0xc0, 0, 0 }
-# endif
-# if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#  define __nan_bytes           { 0, 0, 0xc0, 0x7f }
-# endif
-
-static union { unsigned char __c[4]; float __d; } __nan_union = { __nan_bytes };
-# define NAN    (__nan_union.__d)
-#endif
-
-#ifndef HUGE_VAL
-#define __huge_val_t   union { unsigned char __c[8]; double __d; }
-# if G_BYTE_ORDER == G_BIG_ENDIAN
-#  define __HUGE_VAL_bytes       { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
-# endif
-# if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#  define __HUGE_VAL_bytes       { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
-# endif
-static __huge_val_t __huge_val = { __HUGE_VAL_bytes };
-#  define HUGE_VAL      (__huge_val.__d)
-#endif
-
-
-gdouble ves_icall_System_Math_Floor (gdouble x) {
+
+#include "number-ms.h"
+#include "utils/mono-compiler.h"
+
+static const MonoDouble_double NaN = { .s = { .sign = 0x0, .exp = 0x7FF, .mantHi = 0x80000, .mantLo = 0x0 } };
+
+/* +Infinity */
+static const MonoDouble_double PInfinity = { .s = { .sign = 0x0, .exp = 0x7FF, .mantHi = 0x0, .mantLo = 0x0 } };
+
+/* -Infinity */
+static const MonoDouble_double MInfinity = { .s = { .sign = 0x1, .exp = 0x7FF, .mantHi = 0x0, .mantLo = 0x0 } };
+
+/* +1 */
+static const MonoDouble_double POne = { .s = { .sign = 0x0, .exp = 0x3FF, .mantHi = 0x0, .mantLo = 0x0 } };
+
+/* -1 */
+static const MonoDouble_double MOne = { .s = { .sign = 0x1, .exp = 0x3FF, .mantHi = 0x0, .mantLo = 0x0 } };
+
+static MONO_ALWAYS_INLINE gboolean
+isplusinfinity (gdouble d)
+{
+       return d == PInfinity.d;
+}
+
+static MONO_ALWAYS_INLINE gboolean
+isminusinfinity (gdouble d)
+{
+       return d == MInfinity.d;
+}
+
+static MONO_ALWAYS_INLINE gboolean
+isinfinity (gdouble d)
+{
+       return isplusinfinity (d) || isminusinfinity (d);
+}
+
+static MONO_ALWAYS_INLINE gboolean
+isplusone (gdouble d)
+{
+       return d == POne.d;
+}
+
+static MONO_ALWAYS_INLINE gboolean
+isminusone (gdouble d)
+{
+       return d == MOne.d;
+}
+
+gdouble
+ves_icall_System_Math_Floor (gdouble x)
+{
        return floor(x);
 }
 
-gdouble ves_icall_System_Math_Round (gdouble x) {
-       double int_part, dec_part;
+gdouble
+ves_icall_System_Math_Round (gdouble x)
+{
+       gdouble tmp, floor_tmp;
 
-       int_part = floor(x);
-       dec_part = x - int_part;
-       if (((dec_part == 0.5) &&
-               ((2.0 * ((int_part / 2.0) - floor(int_part / 2.0))) != 0.0)) ||
-               (dec_part > 0.5)) {
-               int_part++;
+       /* If the number has no fractional part do nothing This shortcut is necessary
+        * to workaround precision loss in borderline cases on some platforms */
+       if (x == (gdouble)(gint64) x)
+               return x;
+
+       tmp = x + 0.5;
+       floor_tmp = floor (tmp);
+
+       if (floor_tmp == tmp) {
+               if (fmod (tmp, 2.0) != 0)
+                       floor_tmp -= 1.0;
        }
-       return int_part;
-}
-
-gdouble ves_icall_System_Math_Round2 (gdouble value, gint32 digits, gboolean away_from_zero) {
-#if !defined (HAVE_ROUND) || !defined (HAVE_RINT)
-       double int_part, dec_part;
-#endif
-       double p;
-
-       if (value == HUGE_VAL)
-               return HUGE_VAL;
-       if (value == -HUGE_VAL)
-               return -HUGE_VAL;
-       p = pow(10, digits);
-#if defined (HAVE_ROUND) && defined (HAVE_RINT)
-       if (away_from_zero)
-               return round (value * p) / p;
-       else
-               return rint (value * p) / p;
-#else
-       dec_part = modf (value, &int_part);
-       dec_part *= 1000000000000000ULL;
-       if (away_from_zero && dec_part > 0)
-               dec_part = ceil (dec_part);
-       else
-               dec_part = floor (dec_part);
-       dec_part /= (1000000000000000ULL / p);
-       if (away_from_zero) {
-               if (dec_part > 0)
-                       dec_part = floor (dec_part + 0.5);
-               else
-                       dec_part = ceil (dec_part - 0.5);
-       } else
-               dec_part = ves_icall_System_Math_Round (dec_part);
-       dec_part /= p;
-       return ves_icall_System_Math_Round ((int_part + dec_part) * p) / p;
-#endif
+
+       return copysign (floor_tmp, x);
 }
 
 gdouble 
@@ -130,7 +139,7 @@ gdouble
 ves_icall_System_Math_Acos (gdouble x)
 {
        if (x < -1 || x > 1)
-               return NAN;
+               return NaN.d;
 
        return acos (x);
 }
@@ -139,7 +148,7 @@ gdouble
 ves_icall_System_Math_Asin (gdouble x)
 {
        if (x < -1 || x > 1)
-               return NAN;
+               return NaN.d;
 
        return asin (x);
 }
@@ -153,21 +162,21 @@ ves_icall_System_Math_Atan (gdouble x)
 gdouble 
 ves_icall_System_Math_Atan2 (gdouble y, gdouble x)
 {
-       double result;
+       gdouble result;
+
+       if (isinfinity (x) && isinfinity (y))
+               return NaN.d;
 
-       if ((y == HUGE_VAL && x == HUGE_VAL) ||
-               (y == HUGE_VAL && x == -HUGE_VAL) ||
-               (y == -HUGE_VAL && x == HUGE_VAL) ||
-               (y == -HUGE_VAL && x == -HUGE_VAL)) {
-               return NAN;
-       }
        result = atan2 (y, x);
-       return (result == -0)? 0: result;
+       return result == -0.0 ? 0.0: result;
 }
 
 gdouble 
 ves_icall_System_Math_Exp (gdouble x)
 {
+       if (isinfinity (x))
+               return x < 0 ? 0.0 : x;
+
        return exp (x);
 }
 
@@ -175,9 +184,9 @@ gdouble
 ves_icall_System_Math_Log (gdouble x)
 {
        if (x == 0)
-               return -HUGE_VAL;
+               return MInfinity.d;
        else if (x < 0)
-               return NAN;
+               return NaN.d;
 
        return log (x);
 }
@@ -186,9 +195,9 @@ gdouble
 ves_icall_System_Math_Log10 (gdouble x)
 {
        if (x == 0)
-               return -HUGE_VAL;
+               return MInfinity.d;
        else if (x < 0)
-               return NAN;
+               return NaN.d;
 
        return log10 (x);
 }
@@ -196,43 +205,96 @@ ves_icall_System_Math_Log10 (gdouble x)
 gdouble 
 ves_icall_System_Math_Pow (gdouble x, gdouble y)
 {
-       double result;
-
-       if (isnan(x) || isnan(y)) {
-               return NAN;
-       }
-
-       if ((x == 1 || x == -1) && (y == HUGE_VAL || y == -HUGE_VAL)) {
-               return NAN;
+       gdouble result;
+
+       if (isnan (y))
+               return y;
+       if (isnan (x))
+               return x;
+
+       if (isinfinity (y)) {
+               if (isplusone (x))
+                       return x;
+               if (isminusone (x))
+                       return NaN.d;
        }
 
-       /* This code is for return the same results as MS.NET for certain
-        * limit values */
-       if (x < -9007199254740991.0) {
-               if (y > 9007199254740991.0)
-                       return HUGE_VAL;
-               if (y < -9007199254740991.0)
-                       return 0;
-       }
-
-       result = pow (x, y);
+       /* following are cases from PAL_pow which abstract the implementation of pow for posix and win32 platforms
+        * (https://github.com/dotnet/coreclr/blob/master/src/pal/src/cruntime/finite.cpp#L331) */
 
-       /* This code is for return the same results as MS.NET for certain
-        * limit values */
-       if (isnan(result) &&
-               (x == -1.0) &&
-               ((y > 9007199254740991.0) || (y < -9007199254740991.0))) {
-               return 1;
+       if (isplusinfinity (y) && !isnan (x)) {
+               if (isplusone (x) || isminusone (x))
+                       result = NaN.d;
+               else if (x > MOne.d && x < POne.d)
+                       result = 0.0;
+               else
+                       result = PInfinity.d;
+       } else if (isminusinfinity (y) && !isnan (x)) {
+               if (isplusone (x) || isminusone (x))
+                       result = NaN.d;
+               if (x > MOne.d && x < POne.d)
+                       result = PInfinity.d;
+               else
+                       result = 0.0;
+       } else if (x == 0.0 && y < 0.0) {
+               result = PInfinity.d;
+       } else if (y == 0.0 && isnan (x)) {
+               /* Windows returns NaN for pow(NaN, 0), but POSIX specifies
+                * a return value of 1 for that case.  We need to return
+                * the same result as Windows. */
+               result = NaN.d;
+       } else {
+               result = pow (x, y);
        }
 
-       return (result == -0)? 0: result;
+       if (result == PInfinity.d && x < 0.0 && isfinite (x) && ceil (y / 2) != floor (y / 2))
+               result = MInfinity.d;
+
+       /*
+        * The even/odd test in the if (this one and the one above) used to be ((long long) y % 2 == 0)
+        * on SPARC (long long) y for large y (>2**63) is always 0x7fffffff7fffffff, which
+        * is an odd number, so the test ((long long) y % 2 == 0) will always fail for
+        * large y. Since large double numbers are always even (e.g., the representation of
+        * 1E20+1 is the same as that of 1E20, the last .+1. is too insignificant to be part
+        * of the representation), this test will always return the wrong result for large y.
+        *
+        * The (ceil(y/2) == floor(y/2)) test is slower, but more robust.
+        */
+       if (result == MInfinity.d && x < 0.0 && isfinite (x) && ceil (y / 2) == floor (y / 2))
+               result = PInfinity.d;
+
+       return result == -0.0 ? 0 : result;
 }
 
 gdouble 
 ves_icall_System_Math_Sqrt (gdouble x)
 {
        if (x < 0)
-               return NAN;
+               return NaN.d;
 
        return sqrt (x);
 }
+
+gdouble
+ves_icall_System_Math_Abs_double (gdouble v)
+{
+       return fabs (v);
+}
+
+gfloat
+ves_icall_System_Math_Abs_single (gfloat v)
+{
+       return fabsf (v);
+}
+
+gdouble
+ves_icall_System_Math_Ceiling (gdouble v)
+{
+       return ceil (v);
+}
+
+gdouble
+ves_icall_System_Math_SplitFractionDouble (gdouble *v)
+{
+       return modf (*v, v);
+}
index f8f5778ab418c7fdd52f28a9f8f6cc311d3b9815..bb3cf92bfd5d1906d1a53e04f4c59a0cdacc5e87 100644 (file)
@@ -3,8 +3,10 @@
  *
  * Author:
  *   Dan Lewis (dihlewis@yahoo.co.uk)
+ *   Ludovic Henry (ludovic@xamarin.com)
  *
  * (C) Ximian, Inc. 2002
+ * Copyright 2015 Xamarin, Inc (https://www.xamarin.com)
  */
 
 #ifndef __METADATA_SYSMATH_H__
 
 #include <config.h>
 #include <glib.h>
-#include "mono/utils/mono-compiler.h"
 
-extern gdouble ves_icall_System_Math_Floor (gdouble x);
-extern gdouble ves_icall_System_Math_Round (gdouble x);
-extern gdouble ves_icall_System_Math_Round2 (gdouble value, gint32 digits, gboolean away_from_zero);
+gdouble
+ves_icall_System_Math_Floor (gdouble x);
 
-extern gdouble 
+gdouble
+ves_icall_System_Math_Round (gdouble x);
+
+gdouble
 ves_icall_System_Math_Sin (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Cos (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Tan (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Sinh (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Cosh (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Tanh (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Acos (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Asin (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Atan (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Atan2 (gdouble y, gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Exp (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Log (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Log10 (gdouble x);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Pow (gdouble x, gdouble y);
 
-extern gdouble 
+gdouble
 ves_icall_System_Math_Sqrt (gdouble x);
 
+gdouble
+ves_icall_System_Math_Abs_double (gdouble v);
+
+gfloat
+ves_icall_System_Math_Abs_single (gfloat v);
+
+gdouble
+ves_icall_System_Math_SplitFractionDouble (gdouble *v);
+
+gdouble
+ves_icall_System_Math_Ceiling (gdouble v);
+
 #endif
index 3853f8496288a2826c3cb69eb59b67d3a6b1181a..8da9d2f5d8c409b7dafe59b89caf9b0e6727ef16 100644 (file)
@@ -533,7 +533,6 @@ is_socket_async_callback (MonoImage *system_image, MonoClass *class)
        MonoClass *socket_async_callback_class = NULL;
 
        socket_async_callback_class = mono_class_from_name (system_image, "System.Net.Sockets", "SocketAsyncCallback");
-       g_assert (socket_async_callback_class);
 
        return class == socket_async_callback_class;
 }
@@ -544,7 +543,6 @@ is_async_read_handler (MonoImage *system_image, MonoClass *class)
        MonoClass *async_read_handler_class = NULL;
 
        async_read_handler_class = mono_class_from_name (system_image, "System.Diagnostics", "Process/AsyncReadHandler");
-       g_assert (async_read_handler_class);
 
        return class == async_read_handler_class;
 }
index 3148eec9ce409bccf0a4e8b6044e46fd2f60db21..ca4f58e074d9eb209c10737ac7a9c815248b7005 100644 (file)
@@ -2427,7 +2427,7 @@ compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **c
        p += 4;
        table = (gint32*)p;
 
-       if (fde_count > 1) {
+       if (fde_count > 0) {
                *code_start = amodule->methods [table [0]];
                *code_end = (guint8*)amodule->methods [table [(fde_count - 1) * 2]] + table [fde_count * 2];
        } else {
index 14488d7b435a2eee3e9f37833904ddea34173ae5..6b5d709f905d335e3fb4b37267dfce4527d97797 100644 (file)
@@ -1238,7 +1238,7 @@ mono_remove_critical_edges (MonoCompile *cfg)
 void
 mono_optimize_branches (MonoCompile *cfg)
 {
-       int i, changed = FALSE;
+       int i, count = 0, changed = FALSE;
        MonoBasicBlock *bb, *bbn;
        guint32 niterations;
        MonoInst *bbn_first_inst;
@@ -1261,6 +1261,11 @@ mono_optimize_branches (MonoCompile *cfg)
 
                /* we skip the entry block (exit is handled specially instead ) */
                for (previous_bb = cfg->bb_entry, bb = cfg->bb_entry->next_bb; bb; previous_bb = bb, bb = bb->next_bb) {
+                       count ++;
+                       if (count == 1000) {
+                               MONO_SUSPEND_CHECK ();
+                               count = 0;
+                       }
                        /* dont touch code inside exception clauses */
                        if (bb->region != -1)
                                continue;
index f6c61beb71ba70cc84ec41d79a941a89d512f839..84c2ac34b8fcbb88679e9d5c1ca122ed37d72e8a 100644 (file)
@@ -6916,7 +6916,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        cfg->disable_inline = prev_disable_inline;
        cfg->inline_depth --;
 
-       if ((costs >= 0 && costs < 60) || inline_always) {
+       if ((costs >= 0 && costs < 60) || inline_always || (costs >= 0 && (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))) {
                if (cfg->verbose_level > 2)
                        printf ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
                
index 26fccf0d08ee0864712e5eb1ee2075a06e8bd3ae..f138734181cc24ad5ce1b342e20acf5f9ac6a371 100644 (file)
@@ -813,6 +813,10 @@ mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state,
 
        g_assert (state->valid);
 
+       if (!state->unwind_data [MONO_UNWIND_DATA_DOMAIN])
+               /* Not attached */
+               return;
+
        mono_walk_stack_full (func,
                &state->ctx, 
                state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
index 9924906bd90e625e238e6ca9ad03893a171431f1..0df2d3cd1af74d33f445fa11a8beaef0d820a95e 100644 (file)
@@ -1845,6 +1845,7 @@ typedef struct {
        uint64_t live;
        uint64_t max_live;
        TraceDesc traces;
+       TraceDesc destroy_traces;
 } HandleInfo;
 static HandleInfo handle_info [4];
 
@@ -1991,12 +1992,18 @@ tracked_creation (uintptr_t obj, ClassDesc *cd, uint64_t size, BackTrace *bt, ui
 }
 
 static void
-track_handle (uintptr_t obj, int htype, uint32_t handle)
+track_handle (uintptr_t obj, int htype, uint32_t handle, BackTrace *bt, uint64_t timestamp)
 {
        int i;
        for (i = 0; i < num_tracked_objects; ++i) {
-               if (tracked_objects [i] == obj)
-                       fprintf (outfile, "Object %p referenced from handle %u\n", (void*)obj, handle);
+               if (tracked_objects [i] != obj)
+                       continue;
+               fprintf (outfile, "Object %p referenced from handle %u at %.3f secs.\n", (void*)obj, handle, (timestamp - startup_time) / 1000000000.0);
+               if (bt && bt->count) {
+                       int k;
+                       for (k = 0; k < bt->count; ++k)
+                               fprintf (outfile, "\t%s\n", bt->methods [k]->name);
+               }
        }
 }
 
@@ -2274,31 +2281,72 @@ decode_buffer (ProfContext *ctx)
                                                fprintf (outfile, "moved obj %p to %p\n", (void*)OBJ_ADDR (obj1diff), (void*)OBJ_ADDR (obj2diff));
                                        }
                                }
-                       } else if (subtype == TYPE_GC_HANDLE_CREATED) {
+                       } else if (subtype == TYPE_GC_HANDLE_CREATED || subtype == TYPE_GC_HANDLE_CREATED_BT) {
+                               int has_bt = subtype == TYPE_GC_HANDLE_CREATED_BT;
+                               int num_bt = 0;
+                               MethodDesc *sframes [8];
+                               MethodDesc **frames = sframes;
                                int htype = decode_uleb128 (p, &p);
                                uint32_t handle = decode_uleb128 (p, &p);
                                intptr_t objdiff = decode_sleb128 (p, &p);
+                               if (has_bt) {
+                                       num_bt = 8;
+                                       frames = decode_bt (sframes, &num_bt, p, &p, ptr_base);
+                                       if (!frames) {
+                                               fprintf (outfile, "Cannot load backtrace\n");
+                                               return 0;
+                                       }
+                               }
                                if (htype > 3)
                                        return 0;
-                               handle_info [htype].created++;
-                               handle_info [htype].live++;
-                               add_trace_thread (thread, &handle_info [htype].traces, 1);
-                               /* FIXME: we don't take into account timing here */
-                               if (handle_info [htype].live > handle_info [htype].max_live)
-                                       handle_info [htype].max_live = handle_info [htype].live;
-                               if (num_tracked_objects)
-                                       track_handle (OBJ_ADDR (objdiff), htype, handle);
+                               if ((thread_filter && thread_filter == thread->thread_id) || (time_base >= time_from && time_base < time_to)) {
+                                       handle_info [htype].created++;
+                                       handle_info [htype].live++;
+                                       if (handle_info [htype].live > handle_info [htype].max_live)
+                                               handle_info [htype].max_live = handle_info [htype].live;
+                                       BackTrace *bt;
+                                       if (has_bt)
+                                               bt = add_trace_methods (frames, num_bt, &handle_info [htype].traces, 1);
+                                       else
+                                               bt = add_trace_thread (thread, &handle_info [htype].traces, 1);
+                                       if (num_tracked_objects)
+                                               track_handle (OBJ_ADDR (objdiff), htype, handle, bt, time_base);
+                               }
                                if (debug)
                                        fprintf (outfile, "handle (%s) %u created for object %p\n", get_handle_name (htype), handle, (void*)OBJ_ADDR (objdiff));
-                       } else if (subtype == TYPE_GC_HANDLE_DESTROYED) {
+                               if (frames != sframes)
+                                       free (frames);
+                       } else if (subtype == TYPE_GC_HANDLE_DESTROYED || subtype == TYPE_GC_HANDLE_DESTROYED_BT) {
+                               int has_bt = subtype == TYPE_GC_HANDLE_DESTROYED_BT;
+                               int num_bt = 0;
+                               MethodDesc *sframes [8];
+                               MethodDesc **frames = sframes;
                                int htype = decode_uleb128 (p, &p);
                                uint32_t handle = decode_uleb128 (p, &p);
+                               if (has_bt) {
+                                       num_bt = 8;
+                                       frames = decode_bt (sframes, &num_bt, p, &p, ptr_base);
+                                       if (!frames) {
+                                               fprintf (outfile, "Cannot load backtrace\n");
+                                               return 0;
+                                       }
+                               }
                                if (htype > 3)
                                        return 0;
-                               handle_info [htype].destroyed ++;
-                               handle_info [htype].live--;
+                               if ((thread_filter && thread_filter == thread->thread_id) || (time_base >= time_from && time_base < time_to)) {
+                                       handle_info [htype].destroyed ++;
+                                       handle_info [htype].live--;
+                                       BackTrace *bt;
+                                       if (has_bt)
+                                               bt = add_trace_methods (frames, num_bt, &handle_info [htype].destroy_traces, 1);
+                                       else
+                                               bt = add_trace_thread (thread, &handle_info [htype].destroy_traces, 1);
+                                       /* TODO: track_handle_free () - would need to record and keep track of the associated object address... */
+                               }
                                if (debug)
                                        fprintf (outfile, "handle (%s) %u destroyed\n", get_handle_name (htype), handle);
+                               if (frames != sframes)
+                                       free (frames);
                        }
                        break;
                }
@@ -3178,6 +3226,7 @@ dump_gcs (void)
                        (unsigned long long) (handle_info [i].destroyed),
                        (unsigned long long) (handle_info [i].max_live));
                dump_traces (&handle_info [i].traces, "created");
+               dump_traces (&handle_info [i].destroy_traces, "destroyed");
        }
 }
 
diff --git a/mono/profiler/mono-codeanalyst.c b/mono/profiler/mono-codeanalyst.c
deleted file mode 100644 (file)
index a6d13a0..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * mono-codeanalyst.c: AMD CodeAnalyst profiler
- *
- * Author:
- *   Jonathan Chambers (joncham@gmail.com)
- *
- * (C) 2011 Jonathan Chambers
- *
- * 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.
- */
-#include <mono/metadata/profiler.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/assembly.h>
-#include <string.h>
-#include <glib.h>
-
-#define bool char
-
-#include "CAJITNTFLib.h"
-
-/* called at the end of the program */
-static void
-codeanalyst_shutdown (MonoProfiler *prof)
-{
-       CAJIT_CompleteJITLog ();
-}
-
-static void
-method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
-       if (result == MONO_PROFILE_OK) {
-               gunichar2* name_utf16;
-               MonoClass *klass = mono_method_get_class (method);
-               char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
-               char *name = g_strdup_printf ("%s.%s.%s (%s)", mono_class_get_namespace (klass), mono_class_get_name (klass), mono_method_get_name (method), signature);
-               gpointer code_start = mono_jit_info_get_code_start (jinfo);
-               int code_size = mono_jit_info_get_code_size (jinfo);
-               
-               name_utf16 = g_utf8_to_utf16 (name, strlen (name), NULL, NULL, NULL);
-               
-               CAJIT_LogJITCode ((uintptr_t)code_start, code_size, (wchar_t*)name_utf16);
-               
-               g_free (signature);
-               g_free (name);
-               g_free (name_utf16);
-       }
-}
-
-void
-mono_profiler_startup (const char *desc);
-
-/* the entry point */
-void
-mono_profiler_startup (const char *desc)
-{
-       CAJIT_Initialize ();
-
-       mono_profiler_install (NULL, codeanalyst_shutdown);
-       mono_profiler_install_jit_end (method_jit_result);
-       mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
-}
-
-
index 59d84d189f210eb67a2db8c2d0856cd7d66bcf03..549a7cf0c9085eb4b819e7233c09a5a5fedb2835 100644 (file)
@@ -198,8 +198,8 @@ typedef struct _LogBuffer LogBuffer;
  *
  * type GC format:
  * type: TYPE_GC
- * exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED,
- * TYPE_GC_HANDLE_DESTROYED
+ * exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED[_BT],
+ * TYPE_GC_HANDLE_DESTROYED[_BT]
  * [time diff: uleb128] nanoseconds since last timing
  * if exinfo == TYPE_GC_RESIZE
  *     [heap_size: uleb128] new heap size
@@ -211,15 +211,17 @@ typedef struct _LogBuffer LogBuffer;
  *     [objaddr: sleb128]+ num_objects object pointer differences from obj_base
  *     num is always an even number: the even items are the old
  *     addresses, the odd numbers are the respective new object addresses
- * if exinfo == TYPE_GC_HANDLE_CREATED
+ * if exinfo == TYPE_GC_HANDLE_CREATED[_BT]
  *     [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
  *     upper bits reserved as flags
  *     [handle: uleb128] GC handle value
  *     [objaddr: sleb128] object pointer differences from obj_base
- * if exinfo == TYPE_GC_HANDLE_DESTROYED
+ *     If exinfo == TYPE_GC_HANDLE_CREATED_BT, a backtrace follows.
+ * if exinfo == TYPE_GC_HANDLE_DESTROYED[_BT]
  *     [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
  *     upper bits reserved as flags
  *     [handle: uleb128] GC handle value
+ *     If exinfo == TYPE_GC_HANDLE_DESTROYED_BT, a backtrace follows.
  *
  * type metadata format:
  * type: TYPE_METADATA
@@ -1169,7 +1171,13 @@ gc_roots (MonoProfiler *prof, int num, void **objects, int *root_types, uintptr_
 static void
 gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj)
 {
+       int do_bt = nocalls && InterlockedRead (&runtime_inited) && !notraces;
        uint64_t now;
+       FrameData data;
+
+       if (do_bt)
+               collect_bt (&data);
+
        LogBuffer *logbuffer = ensure_logbuf (
                EVENT_SIZE /* event */ +
                LEB128_SIZE /* time */ +
@@ -1177,21 +1185,36 @@ gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *o
                LEB128_SIZE /* handle */ +
                (op == MONO_PROFILER_GC_HANDLE_CREATED ? (
                        LEB128_SIZE /* obj */
+               ) : 0) +
+               (do_bt ? (
+                       LEB128_SIZE /* flags */ +
+                       LEB128_SIZE /* count */ +
+                       data.count * (
+                               LEB128_SIZE /* method */
+                       )
                ) : 0)
        );
+
        now = current_time ();
        ENTER_LOG (logbuffer, "gchandle");
+
        if (op == MONO_PROFILER_GC_HANDLE_CREATED)
-               emit_byte (logbuffer, TYPE_GC_HANDLE_CREATED | TYPE_GC);
+               emit_byte (logbuffer, (do_bt ? TYPE_GC_HANDLE_CREATED_BT : TYPE_GC_HANDLE_CREATED) | TYPE_GC);
        else if (op == MONO_PROFILER_GC_HANDLE_DESTROYED)
-               emit_byte (logbuffer, TYPE_GC_HANDLE_DESTROYED | TYPE_GC);
+               emit_byte (logbuffer, (do_bt ? TYPE_GC_HANDLE_DESTROYED_BT : TYPE_GC_HANDLE_DESTROYED) | TYPE_GC);
        else
-               return;
+               g_assert_not_reached ();
+
        emit_time (logbuffer, now);
        emit_value (logbuffer, type);
        emit_value (logbuffer, handle);
+
        if (op == MONO_PROFILER_GC_HANDLE_CREATED)
                emit_obj (logbuffer, obj);
+
+       if (do_bt)
+               emit_bt (prof, logbuffer, &data);
+
        EXIT_LOG (logbuffer);
        process_requests (prof);
 }
index a2c0fb25f17cef9802401ac28e635aca0780b642..8fc22e432828e6c7692723d70088411ff3284fad 100644 (file)
@@ -24,6 +24,7 @@
                    load/unload for contexts
                    load/unload/name for assemblies
                removed TYPE_LOAD_ERR flag (profiler never generated it, now removed from the format itself)
+               added TYPE_GC_HANDLE_{CREATED,DESTROYED}_BT
  */
 
 enum {
@@ -56,8 +57,10 @@ enum {
        TYPE_GC_EVENT  = 1 << 4,
        TYPE_GC_RESIZE = 2 << 4,
        TYPE_GC_MOVE   = 3 << 4,
-       TYPE_GC_HANDLE_CREATED   = 4 << 4,
-       TYPE_GC_HANDLE_DESTROYED = 5 << 4,
+       TYPE_GC_HANDLE_CREATED      = 4 << 4,
+       TYPE_GC_HANDLE_DESTROYED    = 5 << 4,
+       TYPE_GC_HANDLE_CREATED_BT   = 6 << 4,
+       TYPE_GC_HANDLE_DESTROYED_BT = 7 << 4,
        /* extended type for TYPE_METHOD */
        TYPE_LEAVE     = 1 << 4,
        TYPE_ENTER     = 2 << 4,
index 5c1cb7cee5eb79460fcd343ab05c4ab09adfe674..f72e5934198cd5fa58cbfae02c5b25abb2f80f29 100644 (file)
@@ -37,7 +37,11 @@ build_profiles += monodroid
 endif
 
 if INSTALL_MONOTOUCH
-build_profiles += monotouch monotouch_runtime monotouch_watch
+build_profiles += monotouch monotouch_runtime
+endif
+
+if INSTALL_MONOTOUCH_WATCH
+build_profiles += monotouch_watch
 endif
 
 if INSTALL_XAMMAC
index 155690d75adad1c75ec255675b443167bc94089f..5e440ab046bf8a6058aed1214e51a7ecc400234e 100644 (file)
@@ -14,7 +14,7 @@ monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)\$"))
 
 # Only include files with /gac/ in path
 #  (Allows packages to contain private assemblies that don't conflict with other packages)
-#monolist=($(printf "%s\n" "${monolist[@]}" | egrep "/gac/"))
+monolist=($(printf "%s\n" "${monolist[@]}" | egrep "/gac/"))
 # Disabled... see ChangeLog
 
 # Set the prefix, unless it is overriden (used when building mono rpms)
index 26ee780169183aff8538e23987818f38721356f4..384451da47c4af2149080cad2de18498e7be577b 100644 (file)
@@ -35,7 +35,7 @@ Mono_Posix_Stdlib_SetLastError (int error_number)
  * we assume that the XPG version is present.
  */
 
-#ifdef _GNU_SOURCE
+#ifdef _GNU_SOURCE && !PLATFORM_ANDROID
 #define mph_min(x,y) ((x) <= (y) ? (x) : (y))
 
 /* If you pass an invalid errno value to glibc 2.3.2's strerror_r, you get
@@ -80,7 +80,27 @@ Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n)
        mph_return_if_size_t_overflow (n);
 
        /* first, check for valid errnum */
+#if PLATFORM_ANDROID
+       /* Android NDK defines _GNU_SOURCE but strerror_r follows the XSI semantics
+        * not the GNU one. XSI version returns an integer, as opposed to the GNU one
+        * which returns pointer to the buffer.
+        */
+       if (strerror_r (errnum, ebuf, sizeof(ebuf)) == -1) {
+               /* XSI strerror_r will return -1 if errno is set, but if we leave the value
+                * alone it breaks Mono.Posix StdioFileStream tests, so we'll ignore the value
+                * and set errno as below
+                */
+               errno = EINVAL;
+               return -1;
+       }
+       r = ebuf;
+#else
        r = strerror_r (errnum, ebuf, sizeof(ebuf));
+#endif
+       if (!r) {
+               errno = EINVAL;
+               return -1;
+       } 
        len = strlen (r);
 
        if (r == ebuf ||