|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
pic_options='-fPIC'
;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
pic_options='-DDLL_EXPORT'
;;
i?86-apple-darwin*|arm-apple-darwin*)
--- /dev/null
+#
+# Appveyor configuration file for CI build of Mono on Windows (under Cygwin)
+#
+# For further details see http://www.appveyor.com
+#
+
+# Use 'unstable' Appveyor build worker image as Appveyor have added Cygwin to this for us
+os: Unstable
+
+#
+# Custom environment variables
+#
+environment:
+ global:
+ CYG_ROOT: C:/cygwin
+ CYG_MIRROR: http://cygwin.mirror.constant.com
+ CYG_CACHE: C:/cygwin/var/cache/setup
+ NSIS_ROOT: C:\nsis
+
+#
+# Initialisation prior to pulling the Mono repository
+#
+init:
+ - 'echo Building Mono for Windows'
+ - 'echo System architecture: %PLATFORM%'
+ - 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
+ - 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
+# Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail
+ - 'git config --global core.autocrlf input'
+
+#
+# Install needed build dependencies
+#
+install:
+# NOTE: Already installed on current Appveyor unstable image
+# - 'echo Retrieving Cygwin'
+# - 'appveyor DownloadFile http://cygwin.com/setup-x86.exe -FileName %CYGROOT%/setup-x86.exe'
+ - 'echo Setting up Cygwin dependencies'
+ - '%CYG_ROOT%\setup-x86.exe -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P autoconf -P automake -P bison -P gcc-core -P gcc-g++ -P mingw-runtime -P mingw-binutils -P mingw-gcc-core -P mingw-gcc-g++ -P mingw-pthreads -P mingw-w32api -P libtool -P make -P python -P gettext-devel -P gettext -P intltool -P libiconv -P pkg-config -P git -P wget -P curl > NUL'
+ - 'echo Check Cygwin setup'
+ - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin"'
+ - 'echo Done setting up Cygwin'
+ - 'echo Retrieving NSIS'
+ - 'appveyor DownloadFile "http://sunet.dl.sourceforge.net/project/nsis/NSIS 2/2.46/nsis-2.46-setup.exe" -FileName nsissetup.exe'
+ - 'echo Setting up NSIS'
+ - 'nsissetup.exe /S /D=%NSIS_ROOT%'
+ - 'echo Done setting up NSIS'
+
+#
+# NOTE: msbuild doesn't work at present so use Cygwin to build
+#
+#build:
+# project: C:\projects\mono\msvc\mono.sln
+# verbosity: detailed
+
+# Cygwin build script
+#
+# NOTES:
+#
+# The stdin/stdout file descriptor appears not to be valid for the Appveyor
+# build which causes failures as certain functions attempt to redirect
+# default file handles. Ensure a dummy file descriptor is opened with exec.
+#
+build_script:
+ - cmd: 'echo Cygwin root is: %CYG_ROOT%'
+ - cmd: 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
+ - cmd: 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
+ - cmd: 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%'
+ - cmd: 'echo Autogen running...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; NOCONFIGURE=1 ./autogen.sh --prefix=/usr/local --with-preview=yes"'
+ - cmd: 'echo Configure running...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; ./configure --host=i686-pc-mingw32"'
+ - cmd: 'echo Pulling monolite latest...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make get-monolite-latest"'
+ - cmd: 'echo Make running...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make"'
+ - cmd: 'echo Installing...'
+ - cmd: 'mkdir %APPVEYOR_BUILD_FOLDER%\install'
+ - cmd: '%CYG_ROOT%/bin/bash --login -lc "export CYGWIN=winsymlinks:native; mount \"$APPVEYOR_BUILD_FOLDER\install\" /usr/local; cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make install; umount /usr/local"'
+# - cmd: 'echo Building package...'
+# - cmd: 'cd %APPVEYOR_BUILD_FOLDER%'
+# - cmd: '%NSIS_ROOT%\makensis /DMILESTONE=%APPVEYOR_REPO_BRANCH% /DSOURCE_INSTALL_DIR=%APPVEYOR_BUILD_FOLDER\install\*.* /DBUILDNUM=%APPVEYOR_BUILD_VERSION% monowiz.win32.nsi'
+# - cmd: 'Building distribution...'
+# - cmd: '%CYG_ROOT%/bin/bash -lc "export CYGWIN=winsymlinks:native; cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make dist"'
+
+#
+# Disable tests for now
+#
+test: off
+
+#
+# NOTE: Currently this is the Mono installation tree. In future we will create an installation package artifact.
+# It has to be relative to the project path. Thus we have installed to within the build tree.
+#
+artifacts:
+ - path: install
+ name: mono-binaries
+ type: zip
# Process this file with autoconf to produce a configure script.
#AC_PREREQ([2.62])
-AC_INIT(mono, [3.10.1],
+AC_INIT(mono, [3.12.1],
[http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
AC_CONFIG_SRCDIR([README.md])
TARGET="unknown"
ACCESS_UNALIGNED="yes"
-JIT_SUPPORTED=no
LIBC="libc.so.6"
INTL="libc.so.6"
SQLITE="libsqlite.so.0"
arch_target=mips;
sgen_supported=true
ACCESS_UNALIGNED="no"
- JIT_SUPPORTED=yes
AC_MSG_CHECKING(for mips n32)
AC_TRY_COMPILE([],[
i*86-*-*)
TARGET=X86;
arch_target=x86;
- JIT_SUPPORTED=yes
case $host_os in
solaris*)
LIBC="libc.so"
x86_64-*-* | amd64-*-*)
TARGET=AMD64;
arch_target=amd64;
- JIT_SUPPORTED=yes
if test "x$ac_cv_sizeof_void_p" = "x4"; then
AC_DEFINE(__mono_ilp32__, 1, [64 bit mode with 4 byte longs and pointers])
sizeof_register=8
TARGET=IA64
arch_target=ia64
ACCESS_UNALIGNED="no"
- JIT_SUPPORTED=yes
LIBC="libc.so.6.1"
INTL="libc.so.6.1"
AC_CHECK_LIB(unwind, _U_dyn_register, [], [AC_MSG_ERROR(library libunwind not found)])
TARGET=SPARC
fi
arch_target=sparc;
- JIT_SUPPORTED=yes
ACCESS_UNALIGNED="no"
case $host_os in
linux*) ;;
CPPFLAGS="$CPPFLAGS -D__mono_ppc__"
fi
arch_target=ppc;
- JIT_SUPPORTED=yes
case $host_os in
linux*|darwin*)
sgen_supported=true
TARGET=ARM;
arch_target=arm;
ACCESS_UNALIGNED="no"
- JIT_SUPPORTED=yes
CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
sgen_supported=true
;;
TARGET=ARM;
arch_target=arm;
ACCESS_UNALIGNED="no"
- JIT_SUPPORTED=yes
sgen_supported=true
AOT_SUPPORTED="yes"
CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
# TARGET=ARM;
# arch_target=arm;
# ACCESS_UNALIGNED="no"
-# JIT_SUPPORTED=yes
# sgen_supported=true
# AOT_SUPPORTED="no"
# ;;
# https://lkml.org/lkml/2012/7/15/133
TARGET=ARM64
arch_target=arm64
- JIT_SUPPORTED=yes
sgen_supported=true
boehm_supported=false
;;
TARGET=S390X;
arch_target=s390x;
ACCESS_UNALIGNED="yes"
- JIT_SUPPORTED=yes
sgen_supported=true
CFLAGS="$CFLAGS -mbackchain -D__USE_STRING_INLINES"
;;
TARGET=ARM;
arch_target=arm;
ACCESS_UNALIGNED="no"
- JIT_SUPPORTED=yes
CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
- jit_wanted=true
# Can't use tls, since it depends on the runtime detection of tls offsets
# in mono-compiler.h
with_tls=pthread
# arch_target=arm
# AC_DEFINE(TARGET_ARM, 1, [...])
# ACCESS_UNALIGNED="no"
-# JIT_SUPPORTED=yes
# sizeof_register=4
# CPPFLAGS="$CPPFLAGS \
# -D__ARM_EABI__ \
# -DDISABLE_SOCKETS \
# -DDISABLE_ATTACH \
# -DUSE_NEWLIB"
-# jit_wanted=true
# Can't use tls, since it depends on the runtime detection of tls offsets
# in mono-compiler.h
# with_tls=pthread
AC_DEFINE(TARGET_ARM, 1, [...])
AC_DEFINE(TARGET_ANDROID, 1, [...])
ACCESS_UNALIGNED="no"
- JIT_SUPPORTED=yes
CPPFLAGS="$CPPFLAGS -D__ARM_EABI__"
- jit_wanted=true
# Can't use tls, since it depends on the runtime detection of tls offsets
# in mono-compiler.h
with_tls=pthread
arch_target=x86;
AC_DEFINE(TARGET_X86, 1, [...])
AC_DEFINE(TARGET_ANDROID, 1, [...])
- JIT_SUPPORTED=yes
CPPFLAGS="$CPPFLAGS"
- jit_wanted=true
sgen_supported=true
# Can't use tls, since it depends on the runtime detection of tls offsets
# in mono-compiler.h
;;
aarch64-*)
TARGET=ARM64
- JIT_SUPPORTED=yes
- jit_wanted=true
;;
*)
AC_MSG_ERROR([Cross compiling is not supported for target $target])
AC_SUBST(SGEN_DEFINES)
AM_CONDITIONAL(SUPPORT_SGEN, test x$buildsgen = xyes)
-USEJIT=false
-if test x$JIT_SUPPORTED = xyes; then
- if $jit_wanted; then
- USEJIT=true
- jit_status="Building and using the JIT"
- else
- AC_ERROR(No JIT support available or selected.)
- fi
-else
- AC_ERROR(No JIT support available or selected.)
-fi
-
-AM_CONDITIONAL(USE_JIT, test x$USEJIT = xtrue)
+jit_status="Building and using the JIT"
libsuffix=".so"
AM_CONDITIONAL(HOST_ARM64, test x$HOST = xARM64)
AM_CONDITIONAL(CROSS_COMPILE, test "x$host" != "x$target")
-AM_CONDITIONAL(JIT_SUPPORTED, test x$JIT_SUPPORTED = xyes)
AM_CONDITIONAL(INCLUDED_LIBGC, test x$libgc = xincluded)
AC_SUBST(LIBC)
SGENPCFILE=
endif
-if JIT_SUPPORTED
pkgconfig_DATA= mono.pc mono-2.pc dotnet.pc dotnet35.pc wcf.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc system.web.extensions_1.0.pc \
system.web.extensions.design_1.0.pc system.web.mvc.pc system.web.mvc2.pc system.web.mvc3.pc aspnetwebstack.pc reactive.pc xbuild12.pc $(SGENPCFILE)
-else
-pkgconfig_DATA= mint.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc
-endif
DISTCLEANFILES= mono-2.pc mono.pc mint.pc dotnet.pc dotnet35.pc wcf.pc mono-nunit.pc mono-cairo.pc mono-options.pc cecil.pc monodoc.pc mono-lineeditor.pc system.web.extensions_1.0.pc \
system.web.extensions.design_1.0.pc system.web.mvc.pc system.web.mvc2.pc system.web.mvc3.pc aspnetwebstack.pc reactive.pc $(SGENPCFILE) mono-sgen-gdb.py
|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
pic_options='-fPIC'
;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
pic_options='-DDLL_EXPORT'
;;
i?86-apple-darwin*|arm-apple-darwin*)
|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
pic_options='-fPIC'
;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
pic_options='-DDLL_EXPORT'
;;
i?86-apple-darwin*|arm-apple-darwin*)
public RelaxngPattern Parse (TextReader source, string baseUri, string defaultNamespace)
{
- this.defaultNamespace = defaultNamespace;
+ this.defaultNamespace = defaultNamespace ?? string.Empty;
if (defaultNamespace != null && defaultNamespace.Length != 0)
nsmgr.AddNamespace (String.Empty, defaultNamespace);
try {
r.Close ();
}
}
+
+ [Test]
+ public void SimpleDefaultNamespace ()
+ {
+ var g = RncParser.ParseRnc (new StringReader ("element e { empty }"));
+ var x = XmlReader.Create (new StringReader ("<e/>"));
+ var r = new RelaxngValidatingReader (x, g);
+ try {
+ while (!r.EOF)
+ r.Read ();
+ } finally {
+ r.Close ();
+ }
+ }
}
}
RNCTESTS = test/RNCTest.xml
RNCTEST_ARCHIVE = anglia-test-suite.zip
-all : relaxngtest.exe anglia-test-runner.exe
+all : relaxngtest.exe #anglia-test-runner.exe
relaxngtest.exe : relaxngtest.cs $(TESTS)
$(MCS_RUNTIME) $(MCS) -debug+ relaxngtest.cs -r:Commons.Xml.Relaxng.dll
StringFormat sf = FlagsToStringFormat (flags);
Size retval;
-
+
+ int proposedWidth;
+ if (proposedSize.Width == 0)
+ proposedWidth = Int32.MaxValue;
+ else {
+ proposedWidth = proposedSize.Width;
+ if ((flags & TextFormatFlags.NoPadding) == 0)
+ proposedWidth -= 9;
+ }
if (dc is Graphics)
- retval = (dc as Graphics).MeasureString (text, font, proposedSize.Width == 0 ? Int32.MaxValue : proposedSize.Width, sf).ToSize ();
+ retval = (dc as Graphics).MeasureString (text, font, proposedWidth, sf).ToSize ();
else
- retval = TextRenderer.MeasureString (text, font, proposedSize.Width == 0 ? Int32.MaxValue : proposedSize.Width, sf).ToSize ();
+ retval = TextRenderer.MeasureString (text, font, proposedWidth, sf).ToSize ();
if (retval.Width > 0 && (flags & TextFormatFlags.NoPadding) == 0)
retval.Width += 9;
Image image = button.Image;
string text = button.Text;
Rectangle content_rect = button.PaddingClientRectangle;
- if (button.TextImageRelation != TextImageRelation.Overlay)
- content_rect.Inflate(-4, -4);
- Size text_size = TextRenderer.MeasureTextInternal (g, text, button.Font, content_rect.Size, button.TextFormatFlags, button.UseCompatibleTextRendering);
+ Size text_size = TextRenderer.MeasureTextInternal (g, text, button.Font, content_rect.Size, button.TextFormatFlags | TextFormatFlags.NoPadding, button.UseCompatibleTextRendering);
Size image_size = image == null ? Size.Empty : image.Size;
- textRectangle = Rectangle.Empty;
+ textRectangle = Rectangle.Inflate (content_rect, -4, -4);
imageRectangle = Rectangle.Empty;
switch (button.TextImageRelation) {
case TextImageRelation.Overlay:
// Overlay is easy, text always goes here
- textRectangle = Rectangle.Inflate (content_rect, -4, -4);
- if (button.Pressed)
- textRectangle.Offset (1, 1);
+ if (button.Pressed)
+ textRectangle.Offset (1, 1);
// Image is dependent on ImageAlign
if (image == null)
imageRectangle = new Rectangle (image_x, image_y, image_width, image_height);
break;
case TextImageRelation.ImageAboveText:
- LayoutTextAboveOrBelowImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+ LayoutTextAboveOrBelowImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
break;
case TextImageRelation.TextAboveImage:
- LayoutTextAboveOrBelowImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+ LayoutTextAboveOrBelowImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
break;
case TextImageRelation.ImageBeforeText:
- LayoutTextBeforeOrAfterImage (content_rect, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+ LayoutTextBeforeOrAfterImage (textRectangle, false, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
break;
case TextImageRelation.TextBeforeImage:
- LayoutTextBeforeOrAfterImage (content_rect, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
+ LayoutTextBeforeOrAfterImage (textRectangle, true, text_size, image_size, button.TextAlign, button.ImageAlign, out textRectangle, out imageRectangle);
break;
}
}
offset += (int)(2 * (excess_height / 3));
if (textFirst) {
- final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, totalArea.Top + offset, textSize.Width, textSize.Height);
+ var textHeight = excess_height >= 0 ? totalArea.Height - imageSize.Height - element_spacing: textSize.Height;
+ final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, totalArea.Top + offset, textSize.Width, textHeight);
final_image_rect = new Rectangle (AlignInRectangle (totalArea, imageSize, imageAlign).Left, final_text_rect.Bottom + element_spacing, imageSize.Width, imageSize.Height);
}
else {
final_image_rect = new Rectangle (AlignInRectangle (totalArea, imageSize, imageAlign).Left, totalArea.Top + offset, imageSize.Width, imageSize.Height);
- final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, final_image_rect.Bottom + element_spacing, textSize.Width, textSize.Height);
+ var textHeight = excess_height >= 0 ? totalArea.Height - final_image_rect.Height : textSize.Height;
+ final_text_rect = new Rectangle (AlignInRectangle (totalArea, textSize, textAlign).Left, final_image_rect.Bottom + element_spacing, textSize.Width, textHeight);
if (final_text_rect.Bottom > totalArea.Bottom)
final_text_rect.Y = totalArea.Top;
buffer [i] = Marshal.ReadByte (prop, i);
Clipboard.Item = Encoding.UTF8.GetString (buffer);
} else if (property == UTF16_STRING) {
- Clipboard.Item = Marshal.PtrToStringUni (prop, Encoding.Unicode.GetMaxCharCount ((int)nitems));
+ Clipboard.Item = Marshal.PtrToStringUni (prop);
} else if (property == RICHTEXTFORMAT)
Clipboard.Item = Marshal.PtrToStringAnsi(prop);
else if (DataFormats.ContainsFormat (property.ToInt32 ())) {
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System
{
- public sealed partial class TimeZoneInfo {
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ sealed partial class TimeZoneInfo {
[SerializableAttribute]
#if MOBILE
[TypeForwardedFrom (Consts.AssemblySystem_Core)]
: db.GetAvailableIds ();
}
- static TimeZoneInfo _GetTimeZone (string name)
+ static TimeZoneInfo _GetTimeZone (string id, string name)
{
if (db == null)
return null;
byte[] buffer = db.GetTimeZoneData (name);
if (buffer == null)
return null;
- return TimeZoneInfo.ParseTZBuffer (name, buffer, buffer.Length);
+ return TimeZoneInfo.ParseTZBuffer (id, buffer, buffer.Length);
}
- internal static TimeZoneInfo GetTimeZone (string id)
+ internal static TimeZoneInfo GetTimeZone (string id, string name)
{
- if (id != null) {
- if (id == "GMT" || id == "UTC")
- return new TimeZoneInfo (id, TimeSpan.FromSeconds (0), id, id, id, null, true);
- if (id.StartsWith ("GMT"))
+ if (name != null) {
+ if (name == "GMT" || name == "UTC")
+ return new TimeZoneInfo (id, TimeSpan.FromSeconds (0), id, name, name, null, disableDaylightSavingTime:true);
+ if (name.StartsWith ("GMT"))
return new TimeZoneInfo (id,
- TimeSpan.FromSeconds (ParseNumericZone (id)),
- id, id, id, null, true);
+ TimeSpan.FromSeconds (ParseNumericZone (name)),
+ id, name, name, null, disableDaylightSavingTime:true);
}
try {
- return _GetTimeZone (id);
+ return _GetTimeZone (id, name);
} catch (Exception) {
return null;
}
static readonly object _lock = new object ();
static TimeZoneInfo defaultZone;
- internal static TimeZoneInfo Default {
+ internal static TimeZoneInfo Local {
get {
lock (_lock) {
if (defaultZone != null)
return defaultZone;
- return defaultZone = GetTimeZone (GetDefaultTimeZoneName ());
+ return defaultZone = GetTimeZone ("Local", GetDefaultTimeZoneName ());
}
}
}
foreach (var id in GetAvailableIds ()) {
Console.Write ("name={0,-40}", id);
try {
- TimeZoneInfo zone = _GetTimeZone (id);
+ TimeZoneInfo zone = _GetTimeZone (id, id);
if (zone != null) {
Console.Write (" {0,-40}", zone);
if (offset.HasValue) {
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Collections.Generic;
using System.Globalization;
namespace System
{
- public partial class TimeZoneInfo
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ partial class TimeZoneInfo
{
public static TimeZoneInfo FromSerializedString (string source)
{
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System
{
- public sealed partial class TimeZoneInfo
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ sealed partial class TimeZoneInfo
{
[SerializableAttribute]
#if MOBILE
[assembly:TypeForwardedTo (typeof(TimeZoneInfo))]
-#elif (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#elif INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Collections.Generic;
using System.Collections.ObjectModel;
[TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
#endif
[SerializableAttribute]
- public sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
{
TimeSpan baseUtcOffset;
public TimeSpan BaseUtcOffset {
}
}
+ /*
+ TimeZone transitions are stored when there is a change on the base offset.
+ */
+ private List<KeyValuePair<DateTime, TimeType>> transitions;
+
static TimeZoneInfo CreateLocal ()
{
#if MONODROID
- return AndroidTimeZones.Default;
+ return AndroidTimeZones.Local;
#elif MONOTOUCH
using (Stream stream = GetMonoTouchData (null)) {
return BuildFromStream ("Local", stream);
}
#elif LIBC
+ var tz = Environment.GetEnvironmentVariable ("TZ");
+ if (tz != null) {
+ if (tz == String.Empty)
+ return Utc;
+ try {
+ return FindSystemTimeZoneByFileName (tz, Path.Combine (TimeZoneDirectory, tz));
+ } catch {
+ return Utc;
+ }
+ }
+
try {
return FindSystemTimeZoneByFileName ("Local", "/etc/localtime");
} catch {
if (dateTime.Kind == DateTimeKind.Utc)
return dateTime;
- //FIXME: do not rely on DateTime implementation !
- return DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc);
+ return ConvertTimeToUtc (dateTime, TimeZoneInfo.Local);
}
public static DateTime ConvertTimeToUtc (DateTime dateTime, TimeZoneInfo sourceTimeZone)
if (sourceTimeZone.IsInvalidTime (dateTime))
throw new ArgumentException ("dateTime parameter is an invalid time");
- if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone == TimeZoneInfo.Utc)
- return dateTime;
-
if (dateTime.Kind == DateTimeKind.Utc)
return dateTime;
- if (dateTime.Kind == DateTimeKind.Local)
- return ConvertTimeToUtc (dateTime);
-
if (sourceTimeZone.IsAmbiguousTime (dateTime) || !sourceTimeZone.IsDaylightSavingTime (dateTime))
return DateTime.SpecifyKind (dateTime - sourceTimeZone.BaseUtcOffset, DateTimeKind.Utc);
else {
}
#endif
#if MONODROID
- var timeZoneInfo = AndroidTimeZones.GetTimeZone (id);
+ var timeZoneInfo = AndroidTimeZones.GetTimeZone (id, id);
if (timeZoneInfo == null)
throw new TimeZoneNotFoundException ();
return timeZoneInfo;
#endif
#if MONODROID
foreach (string id in AndroidTimeZones.GetAvailableIds ()) {
- var tz = AndroidTimeZones.GetTimeZone (id);
+ var tz = AndroidTimeZones.GetTimeZone (id, id);
if (tz != null)
systemTimeZones.Add (tz);
}
public TimeSpan GetUtcOffset (DateTime dateTime)
{
- if (IsDaylightSavingTime (dateTime)) {
- AdjustmentRule rule = GetApplicableRule (dateTime);
- if (rule != null)
- return BaseUtcOffset + rule.DaylightDelta;
- }
-
- return BaseUtcOffset;
+ bool isDST;
+ return GetUtcOffset (dateTime, out isDST);
}
public TimeSpan GetUtcOffset (DateTimeOffset dateTimeOffset)
throw new NotImplementedException ();
}
+ private TimeSpan GetUtcOffset (DateTime dateTime, out bool isDST)
+ {
+ isDST = false;
+
+ TimeZoneInfo tz = this;
+ if (dateTime.Kind == DateTimeKind.Utc)
+ tz = TimeZoneInfo.Utc;
+
+ if (dateTime.Kind == DateTimeKind.Local)
+ tz = TimeZoneInfo.Local;
+
+ bool isTzDst;
+ var tzOffset = GetUtcOffset (dateTime, tz, out isTzDst);
+
+ if (tz == this) {
+ isDST = isTzDst;
+ return tzOffset;
+ }
+
+ var utcTicks = dateTime.Ticks - tzOffset.Ticks;
+ if (utcTicks < 0 || utcTicks > DateTime.MaxValue.Ticks)
+ return BaseUtcOffset;
+
+ var utcDateTime = new DateTime (utcTicks, DateTimeKind.Utc);
+
+ return GetUtcOffset (utcDateTime, this, out isDST);
+ }
+
+ private static TimeSpan GetUtcOffset (DateTime dateTime, TimeZoneInfo tz, out bool isDST)
+ {
+ if (dateTime.Kind == DateTimeKind.Local && tz != TimeZoneInfo.Local)
+ throw new Exception ();
+
+ isDST = false;
+
+ if (tz == TimeZoneInfo.Utc)
+ return TimeSpan.Zero;
+
+ TimeSpan offset;
+ if (tz.TryGetTransitionOffset(dateTime, out offset, out isDST))
+ return offset;
+
+ if (dateTime.Kind == DateTimeKind.Utc) {
+ var utcRule = tz.GetApplicableRule (dateTime);
+ if (utcRule != null && tz.IsInDST (utcRule, dateTime)) {
+ isDST = true;
+ return tz.BaseUtcOffset + utcRule.DaylightDelta;
+ }
+
+ return tz.BaseUtcOffset;
+ }
+
+ var stdTicks = dateTime.Ticks - tz.BaseUtcOffset.Ticks;
+ if (stdTicks < 0 || stdTicks > DateTime.MaxValue.Ticks)
+ return tz.BaseUtcOffset;
+
+ var stdUtcDateTime = new DateTime (stdTicks, DateTimeKind.Utc);
+ var tzRule = tz.GetApplicableRule (stdUtcDateTime);
+
+ DateTime dstUtcDateTime = DateTime.MinValue;
+ if (tzRule != null) {
+ var dstTicks = stdUtcDateTime.Ticks - tzRule.DaylightDelta.Ticks;
+ if (dstTicks < 0 || dstTicks > DateTime.MaxValue.Ticks)
+ return tz.BaseUtcOffset;
+
+ dstUtcDateTime = new DateTime (dstTicks, DateTimeKind.Utc);
+ }
+
+ if (tzRule != null && tz.IsInDST (tzRule, stdUtcDateTime) && tz.IsInDST (tzRule, dstUtcDateTime)) {
+ isDST = true;
+ return tz.BaseUtcOffset + tzRule.DaylightDelta;
+ }
+
+ return tz.BaseUtcOffset;
+ }
+
public bool HasSameRules (TimeZoneInfo other)
{
if (other == null)
throw new NotImplementedException ();
}
+ private bool IsInDST (AdjustmentRule rule, DateTime dateTime)
+ {
+ // Check whether we're in the dateTime year's DST period
+ if (IsInDSTForYear (rule, dateTime, dateTime.Year))
+ return true;
+
+ // We might be in the dateTime previous year's DST period
+ return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
+ }
+
bool IsInDSTForYear (AdjustmentRule rule, DateTime dateTime, int year)
{
DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, year);
if (!SupportsDaylightSavingTime)
return false;
-
- //FIXME: do not rely on DateTime implementation !
- if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == TimeZoneInfo.Local)
- return dateTime.IsDaylightSavingTime ();
-
- //FIXME: do not rely on DateTime implementation !
- if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Utc)
- return IsDaylightSavingTime (DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc));
-
- AdjustmentRule rule = GetApplicableRule (dateTime.Date);
- if (rule == null)
- return false;
- // Check whether we're in the dateTime year's DST period
- if (IsInDSTForYear (rule, dateTime, dateTime.Year))
- return true;
+ bool isDst;
+ GetUtcOffset (dateTime, out isDst);
- // We might be in the dateTime previous year's DST period
- return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
+ return isDst;
}
public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset)
return null;
}
+ private bool TryGetTransitionOffset (DateTime dateTime, out TimeSpan offset,out bool isDst)
+ {
+ offset = BaseUtcOffset;
+ isDst = false;
+
+ if (transitions == null)
+ return false;
+
+ //Transitions are always in standard time
+ DateTime date = dateTime;
+
+ if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Local)
+ date = date.ToUniversalTime () + BaseUtcOffset;
+
+ if (dateTime.Kind == DateTimeKind.Utc && this != TimeZoneInfo.Utc)
+ date = date + BaseUtcOffset;
+
+ for (var i = transitions.Count - 1; i >= 0; i--) {
+ var pair = transitions [i];
+ DateTime ttime = pair.Key;
+ TimeType ttype = pair.Value;
+
+ if (ttime > date)
+ continue;
+
+ offset = new TimeSpan (0, 0, ttype.Offset);
+ isDst = ttype.IsDst;
+
+ return true;
+ }
+
+ return false;
+ }
+
private static DateTime TransitionPoint (TransitionTime transition, int year)
{
if (transition.IsFixedDateRule)
bool dst_observed = false;
DateTime dst_start = DateTime.MinValue;
List<AdjustmentRule> adjustmentRules = new List<AdjustmentRule> ();
+ bool storeTransition = false;
for (int i = 0; i < transitions.Count; i++) {
var pair = transitions [i];
standardDisplayName = ttype.Name;
daylightDisplayName = null;
baseUtcOffset = new TimeSpan (0, 0, ttype.Offset);
+ if (adjustmentRules.Count > 0) // We ignore AdjustmentRules but store transitions.
+ storeTransition = true;
adjustmentRules = new List<AdjustmentRule> ();
dst_observed = false;
}
}
}
- if (adjustmentRules.Count == 0) {
+ TimeZoneInfo tz;
+ if (adjustmentRules.Count == 0 && !storeTransition) {
TimeType t = (TimeType)time_types [0];
if (standardDisplayName == null) {
standardDisplayName = t.Name;
baseUtcOffset = new TimeSpan (0, 0, t.Offset);
}
- return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName);
+ tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName);
} else {
- return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ());
+ tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ());
}
+
+ if (storeTransition)
+ tz.transitions = transitions;
+
+ return tz;
}
static Dictionary<int, string> ParseAbbreviations (byte [] buffer, int index, int count)
DateTime afterDST = new DateTime (2007, 10, 28, 2, 0, 0, DateTimeKind.Unspecified);
Assert.IsFalse (london.IsDaylightSavingTime (beforeDST), "Just before DST");
Assert.IsTrue (london.IsDaylightSavingTime (startDST), "the first seconds of DST");
- Assert.IsTrue (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
+ Assert.IsFalse (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
Assert.IsFalse (london.IsDaylightSavingTime (afterDST), "Just after DST");
}
Assert.IsTrue (london.Equals (deserialized));
}
}
+
+ [TestFixture]
+ public class MultipleDaylightSavingTimeTests {
+ private TimeZoneInfo cairo;
+ private DateTime dst1Start;
+ private DateTime dst1End;
+ private DateTime dst2Start;
+ private DateTime dst2End;
+
+ private TimeSpan baseUtcOffset;
+ private TimeSpan dstUtcOffset;
+ private TimeSpan dstOffset;
+
+ [SetUp]
+ public void CreateTimeZones ()
+ {
+ /*
+ From 1/1/2014 12:00:00 AM to 6/30/2014 12:00:00 AM
+ Delta: 01:00:00
+ Begins at 12:00 AM on 16 May
+ Ends at 1:00 AM on 29 June
+ From 7/1/2014 12:00:00 AM to 12/31/2014 12:00:00 AM
+ Delta: 01:00:00
+ Begins at 12:00 AM on 29 July
+ Ends at 12:00 AM on 26 September
+ */
+ dst1Start = new DateTime (2014, 5, 16);
+ dst1End = new DateTime (2014, 6, 29);
+ dst2Start = new DateTime (2014, 7, 29);
+ dst2End = new DateTime (2014, 9, 26);
+
+ baseUtcOffset = new TimeSpan (2, 0, 0);
+ dstUtcOffset = new TimeSpan (3, 0, 0);
+ dstOffset = dstUtcOffset - baseUtcOffset;
+
+ var rule1 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+ new DateTime (2014, 1, 1), new DateTime (2014, 6, 30), dstOffset,
+ CreateFixedDateRule (dst1Start), CreateFixedDateRule (dst1End));
+
+ var rule2 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+ new DateTime (2014, 7, 1), new DateTime (2014, 12, 31), dstOffset,
+ CreateFixedDateRule (dst2Start), CreateFixedDateRule (dst2End));
+
+ cairo = TimeZoneInfo.CreateCustomTimeZone ("Africa/Cairo", baseUtcOffset, "Africa/Cairo", "EET", "EEST",
+ new [] {rule1, rule2});
+ }
+
+ private static TimeZoneInfo.TransitionTime CreateFixedDateRule (DateTime dateTime)
+ {
+ var time = new DateTime (dateTime.Ticks - dateTime.Date.Ticks);
+ return TimeZoneInfo.TransitionTime.CreateFixedDateRule (time, dateTime.Month, dateTime.Day);
+ }
+
+ [Test]
+ public void GetUtcOffset_FromUTC ()
+ {
+ var d = dst1Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst1End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+ }
+
+ [Test]
+ public void GetUtcOffset_FromLocal ()
+ {
+ var d = dst1Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst1End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+ }
+
+ [Test]
+ public void GetUtcOffset_FromUnspecified ()
+ {
+ var d = dst1Start.Add (dstOffset);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst1End.Add (-dstOffset);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2Start.Add (dstOffset);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2End.Add (-dstOffset);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+ }
+ }
}
}
#endif
#if NET_4_5
public virtual ReadEntityBodyMode ReadEntityBodyMode { get { NotImplemented(); return ReadEntityBodyMode.Classic; } }
-
- public virtual UnvalidatedRequestValuesBase Unvalidated { get { NotImplemented (); return null; } }
#endif
public virtual Uri Url { get { NotImplemented (); return null; } }
public virtual bool SuppressContent { get { NotImplemented (); return false; } set { NotImplemented (); } }
+#if NET_4_5
+ public virtual bool SuppressFormsAuthenticationRedirect { get { NotImplemented (); return false; } set { NotImplemented (); } }
+#endif
+
public virtual bool TrySkipIisCustomErrors { get { NotImplemented (); return false; } set { NotImplemented (); } }
set { w.SuppressContent = value; }
}
+#if NET_4_5
+ public override bool SuppressFormsAuthenticationRedirect {
+ get { return w.SuppressFormsAuthenticationRedirect; }
+ set { w.SuppressFormsAuthenticationRedirect = value; }
+ }
+#endif
+
public override bool TrySkipIisCustomErrors {
get { return w.TrySkipIisCustomErrors; }
set { w.TrySkipIisCustomErrors = value; }
static readonly char[] pathTrimChars = { '/' };
static readonly object suppressAppReloadLock = new object ();
static readonly object saveLocationsCacheLock = new object ();
+ static readonly object getSectionLock = new object ();
// See comment for the cacheLock field at top of System.Web.Caching/Cache.cs
static readonly ReaderWriterLockSlim sectionCacheLock;
cachePath = path;
}
- ConfigurationSection section = c.GetSection (sectionName);
+ ConfigurationSection section;
+ lock (getSectionLock) {
+ section = c.GetSection (sectionName);
+ }
if (section == null)
return null;
value = collection;
}
#else
- object value = SettingsMappingManager.MapSection (get_runtime_object.Invoke (section, new object [0]));
+ object value = SettingsMappingManager.MapSection (section.GetRuntimeObject ());
#endif
if (cachePath != null)
cacheKey = baseCacheKey ^ cachePath.GetHashCode ();
configurations.Remove (GetCurrentPath (ctx));
}
+#if TARGET_J2EE
readonly static MethodInfo get_runtime_object = typeof (ConfigurationSection).GetMethod ("GetRuntimeObject", BindingFlags.NonPublic | BindingFlags.Instance);
+#endif
public static object GetWebApplicationSection (string sectionName)
{
if (context.Response.StatusCode != 401 || context.Request.QueryString ["ReturnUrl"] != null)
return;
+#if NET_4_5
+ if (context.Response.StatusCode == 401 && context.Response.SuppressFormsAuthenticationRedirect)
+ return;
+#endif
+
string loginPage;
InitConfig (context);
#if NET_2_0
}
} catch (Exception e) {
initialization_exception = e;
+ Console.Error.WriteLine("Exception while initOnce: "+e.ToString());
+ // Once initialization_exception != null, we always respond with this exception
+ // You have to restart the HttpApplication to "unlock" it
+ Console.Error.WriteLine("Please restart your app to unlock it");
} finally {
if (mustNullContext)
context = null;
if (initialization_exception != null) {
Exception e = initialization_exception;
HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort);
+ context.Response.StatusCode = 500;
FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ());
PipelineDone ();
return;
set;
}
+#if NET_4_5
+ public bool SuppressFormsAuthenticationRedirect {
+ get;
+ set;
+ }
+#endif
+
public bool TrySkipIisCustomErrors {
get;
set;
if (valueCache != null)
return valueCache;
if (ValueBufferStart >= 0) {
-//Console.WriteLine (NodeType + " / " + ValueBuffer.Length + " / " + ValueBufferStart + " / " + ValueBufferEnd);
valueCache = Reader.valueBuffer.ToString (ValueBufferStart, ValueBufferEnd - ValueBufferStart);
return valueCache;
}
value,
false);
ati.Value = value;
+ ati.ValueTokenStartIndex = ati.ValueTokenEndIndex = currentAttributeValue;
attributeCount++;
}
var xtr = new XmlTextReader (ms);
xtr.Read ();
}
+
+ [Test]
+ public void XmlDeclarationReadAttributeValue ()
+ {
+ const string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?><hello />";
+ var reader = new XmlTextReader (new StringReader (input));
+ reader.WhitespaceHandling = WhitespaceHandling.All;
+ reader.Read ();
+
+ Assert.AreEqual ("1.0", reader.GetAttribute ("version"), "#0");
+ Assert.AreEqual ("utf-8", reader.GetAttribute ("encoding"), "#0-2");
+
+ Assert.IsTrue (reader.MoveToNextAttribute (), "#1");
+ Assert.AreEqual ("1.0", reader.Value, "#1-1");
+ Assert.IsTrue (reader.ReadAttributeValue (), "#2");
+ Assert.AreEqual ("1.0", reader.Value, "#3");
+ Assert.IsFalse (reader.ReadAttributeValue (), "#4");
+
+ Assert.IsTrue (reader.MoveToNextAttribute (), "#5");
+ Assert.AreEqual ("utf-8", reader.Value, "#5-1");
+ Assert.IsTrue (reader.ReadAttributeValue (), "#6");
+ Assert.AreEqual ("utf-8", reader.Value, "#7");
+ Assert.IsFalse (reader.ReadAttributeValue (), "#8");
+
+ Assert.IsFalse (reader.MoveToNextAttribute (), "#9");
+ Assert.IsFalse (reader.ReadAttributeValue (), "#10");
+ }
+
+ [Test]
+ public void XmlDeclarationReadAttributeValue2 ()
+ {
+ const string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?><hello />";
+ var reader = new XmlTextReader (new StringReader (input));
+ reader.WhitespaceHandling = WhitespaceHandling.All;
+ reader.Read ();
+ Assert.IsTrue (reader.MoveToNextAttribute (), "#1a");
+ Assert.IsTrue (reader.ReadAttributeValue (), "#1b");
+ Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#1c");
+ Assert.AreEqual ("1.0", reader.Value, "#1d");
+ Assert.IsFalse (reader.ReadAttributeValue(), "#1e");
+
+ Assert.IsTrue (reader.MoveToNextAttribute(), "#2a");
+ Assert.IsTrue (reader.ReadAttributeValue(), "#2b");
+ Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#2c");
+ Assert.AreEqual ("utf-8", reader.Value, "#2d");
+ Assert.IsFalse (reader.ReadAttributeValue(), "#2e");
+
+ Assert.IsFalse (reader.MoveToNextAttribute(), "#3");
+ Assert.IsFalse (reader.ReadAttributeValue(), "#4");
+ Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#5");
+ }
}
}
// Probe for Linux-styled devices: /dev/ttyS* or /dev/ttyUSB*
//
foreach (string dev in ttys) {
- if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB")){
+ if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM")) {
linux_style = true;
break;
}
foreach (string dev in ttys) {
if (linux_style){
- if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB"))
+ if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
serial_ports.Add (dev);
} else {
if (dev != "/dev/tty" && dev.StartsWith ("/dev/tty") && !dev.StartsWith ("/dev/ttyC"))
internal SearchPattern2 Pattern {
get {
if (pattern == null) {
- pattern = new SearchPattern2 (MangledFilter);
+ if (watcher.GetType () == typeof (KeventWatcher))
+ pattern = new SearchPattern2 (MangledFilter, true); //assume we want to ignore case (OS X)
+ else
+ pattern = new SearchPattern2 (MangledFilter);
}
return pattern;
}
ErrorEvent,
RenameEvent
}
- private void RaiseEvent (Delegate ev, EventArgs arg, EventType evtype)
- {
- if (ev == null)
- return;
-
- if (synchronizingObject == null) {
- switch (evtype) {
- case EventType.RenameEvent:
- ((RenamedEventHandler)ev).BeginInvoke (this, (RenamedEventArgs) arg, null, null);
- break;
- case EventType.ErrorEvent:
- ((ErrorEventHandler)ev).BeginInvoke (this, (ErrorEventArgs) arg, null, null);
- break;
- case EventType.FileSystemEvent:
- ((FileSystemEventHandler)ev).BeginInvoke (this, (FileSystemEventArgs) arg, null, null);
- break;
- }
- return;
- }
- synchronizingObject.BeginInvoke (ev, new object [] {this, arg});
- }
-
protected void OnChanged (FileSystemEventArgs e)
{
- RaiseEvent (Changed, e, EventType.FileSystemEvent);
+ if (Changed == null)
+ return;
+
+ if (synchronizingObject == null)
+ Changed (this, e);
+ else
+ synchronizingObject.BeginInvoke (Changed, new object[] { this, e });
}
protected void OnCreated (FileSystemEventArgs e)
{
- RaiseEvent (Created, e, EventType.FileSystemEvent);
+ if (Created == null)
+ return;
+
+ if (synchronizingObject == null)
+ Created (this, e);
+ else
+ synchronizingObject.BeginInvoke (Created, new object[] { this, e });
}
protected void OnDeleted (FileSystemEventArgs e)
{
- RaiseEvent (Deleted, e, EventType.FileSystemEvent);
+ if (Deleted == null)
+ return;
+
+ if (synchronizingObject == null)
+ Deleted (this, e);
+ else
+ synchronizingObject.BeginInvoke (Deleted, new object[] { this, e });
}
- protected void OnError (ErrorEventArgs e)
+ internal void OnError (ErrorEventArgs e)
{
- RaiseEvent (Error, e, EventType.ErrorEvent);
+ if (Error == null)
+ return;
+
+ if (synchronizingObject == null)
+ Error (this, e);
+ else
+ synchronizingObject.BeginInvoke (Error, new object[] { this, e });
}
protected void OnRenamed (RenamedEventArgs e)
{
- RaiseEvent (Renamed, e, EventType.RenameEvent);
+ if (Renamed == null)
+ return;
+
+ if (synchronizingObject == null)
+ Renamed (this, e);
+ else
+ synchronizingObject.BeginInvoke (Renamed, new object[] { this, e });
}
public WaitForChangedResult WaitForChanged (WatcherChangeTypes changeType)
//
// Authors:
// Geoff Norton (gnorton@customerdna.com)
+// Cody Russell (cody@xamarin.com)
+// Alexis Christoforides (lexas@xamarin.com)
//
// (c) 2004 Geoff Norton
// Copyright 2014 Xamarin Inc
using System;
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
+using System.Reflection;
namespace System.IO {
VM = -11
}
+ [Flags]
enum FilterFlags : uint {
ReadPoll = EventFlags.Flag0,
ReadOutOfBand = EventFlags.Flag1,
TimerNanoSeconds = 0x00000004,
TimerAbsolute = 0x00000008,
}
-
+
+ [StructLayout(LayoutKind.Sequential)]
struct kevent : IDisposable {
- public int ident;
+ public UIntPtr ident;
public EventFilter filter;
public EventFlags flags;
public FilterFlags fflags;
- public int data;
+ public IntPtr data;
public IntPtr udata;
public void Dispose ()
if (udata != IntPtr.Zero)
Marshal.FreeHGlobal (udata);
}
+
+
}
+ [StructLayout(LayoutKind.Sequential)]
struct timespec {
- public int tv_sec;
- public int tv_usec;
+ public IntPtr tv_sec;
+ public IntPtr tv_usec;
}
- class KeventFileData {
- public FileSystemInfo fsi;
- public DateTime LastAccessTime;
- public DateTime LastWriteTime;
+ class PathData
+ {
+ public string Path;
+ public bool IsDirectory;
+ public int Fd;
+ }
- public KeventFileData(FileSystemInfo fsi, DateTime LastAccessTime, DateTime LastWriteTime) {
- this.fsi = fsi;
- this.LastAccessTime = LastAccessTime;
- this.LastWriteTime = LastWriteTime;
+ class KqueueMonitor : IDisposable
+ {
+ public int Connection
+ {
+ get { return conn; }
}
- }
- class KeventData {
- public FileSystemWatcher FSW;
- public string Directory;
- public string FileMask;
- public bool IncludeSubdirs;
- public bool Enabled;
- public Hashtable DirEntries;
- public kevent ev;
- }
+ public KqueueMonitor (FileSystemWatcher fsw)
+ {
+ this.fsw = fsw;
+ this.conn = -1;
+ }
- class KeventWatcher : IFileWatcher
- {
- static bool failed;
- static KeventWatcher instance;
- static Hashtable watches;
- static Hashtable requests;
- static Thread thread;
- static int conn;
- static bool stop;
-
- private KeventWatcher ()
+ public void Dispose ()
{
+ CleanUp ();
}
-
- // Locked by caller
- public static bool GetInstance (out IFileWatcher watcher)
+
+ public void Start ()
{
- if (failed == true) {
- watcher = null;
- return false;
- }
+ lock (stateLock) {
+ if (started)
+ return;
- if (instance != null) {
- watcher = instance;
- return true;
- }
+ conn = kqueue ();
- watches = Hashtable.Synchronized (new Hashtable ());
- requests = Hashtable.Synchronized (new Hashtable ());
- conn = kqueue();
- if (conn == -1) {
- failed = true;
- watcher = null;
- return false;
- }
+ if (conn == -1)
+ throw new IOException (String.Format (
+ "kqueue() error at init, error code = '{0}'", Marshal.GetLastWin32Error ()));
+
+ thread = new Thread (() => DoMonitor ());
+ thread.IsBackground = true;
+ thread.Start ();
- instance = new KeventWatcher ();
- watcher = instance;
- return true;
+ startedEvent.WaitOne ();
+
+ if (failedInit) {
+ thread.Join ();
+ CleanUp ();
+ throw new IOException ("Monitor thread failed while initializing.");
+ }
+ else
+ started = true;
+ }
}
-
- public void StartDispatching (FileSystemWatcher fsw)
+
+ public void Stop ()
{
- KeventData data;
- lock (this) {
- if (thread == null) {
- thread = new Thread (new ThreadStart (Monitor));
- thread.IsBackground = true;
- thread.Start ();
- }
+ lock (stateLock) {
+ if (!started)
+ return;
+
+ requestStop = true;
+ thread.Join ();
+ requestStop = false;
- data = (KeventData) watches [fsw];
+ CleanUp ();
+ started = false;
}
+ }
- if (data == null) {
- data = new KeventData ();
- data.FSW = fsw;
- data.Directory = fsw.FullPath;
- data.FileMask = fsw.MangledFilter;
- data.IncludeSubdirs = fsw.IncludeSubdirectories;
-
- data.Enabled = true;
- lock (this) {
- StartMonitoringDirectory (data);
- watches [fsw] = data;
- stop = false;
- }
- }
+ void CleanUp ()
+ {
+ if (conn != -1)
+ close (conn);
+
+ conn = -1;
+
+ foreach (int fd in fdsDict.Keys)
+ close (fd);
+
+ fdsDict.Clear ();
+ pathsDict.Clear ();
}
- static void StartMonitoringDirectory (KeventData data)
+ void DoMonitor ()
{
- DirectoryInfo dir = new DirectoryInfo (data.Directory);
- if(data.DirEntries == null) {
- data.DirEntries = new Hashtable();
- foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() )
- data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime));
+ Exception exc = null;
+ failedInit = false;
+
+ try {
+ Setup ();
+ } catch (Exception e) {
+ failedInit = true;
+ exc = e;
+ } finally {
+ startedEvent.Set ();
}
- int fd = open(data.Directory, 0, 0);
- kevent ev = new kevent();
- ev.udata = IntPtr.Zero;
- timespec nullts = new timespec();
- nullts.tv_sec = 0;
- nullts.tv_usec = 0;
- if (fd > 0) {
- ev.ident = fd;
- ev.filter = EventFilter.Vnode;
- ev.flags = EventFlags.Add | EventFlags.Enable | EventFlags.OneShot;
- ev.fflags = // 20 | 2 | 1 | 8;
- FilterFlags.VNodeDelete |
- FilterFlags.VNodeWrite |
- FilterFlags.VNodeAttrib |
- // The following two values are the equivalent of the original value "20", but we suspect the original author meant
- // 0x20, we will review later with some test cases
- FilterFlags.VNodeLink |
- FilterFlags.VNodeExtend;
- ev.data = 0;
- ev.udata = Marshal.StringToHGlobalAuto (data.Directory);
- kevent outev = new kevent();
- outev.udata = IntPtr.Zero;
- kevent (conn, ref ev, 1, ref outev, 0, ref nullts);
- data.ev = ev;
- requests [fd] = data;
- }
-
- if (!data.IncludeSubdirs)
+ if (failedInit) {
+ fsw.OnError (new ErrorEventArgs (exc));
return;
+ }
+ try {
+ Monitor ();
+ } catch (Exception e) {
+ exc = e;
+ } finally {
+ if (!requestStop) { // failure
+ CleanUp ();
+ started = false;
+ }
+ if (exc != null)
+ fsw.OnError (new ErrorEventArgs (exc));
+ }
}
- public void StopDispatching (FileSystemWatcher fsw)
- {
- KeventData data;
- lock (this) {
- data = (KeventData) watches [fsw];
- if (data == null)
- return;
+ void Setup ()
+ {
+ var initialFds = new List<int> ();
- StopMonitoringDirectory (data);
- watches.Remove (fsw);
- if (watches.Count == 0)
- stop = true;
+ // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks.
+ // If so, introduce a fixup step.
+ int fd = open (fsw.FullPath, O_EVTONLY, 0);
+ var resolvedFullPath = GetFilenameFromFd (fd);
+ close (fd);
- if (!data.IncludeSubdirs)
- return;
+ if (resolvedFullPath != fsw.FullPath)
+ fixupPath = resolvedFullPath;
+ else
+ fixupPath = null;
+
+ Scan (fsw.FullPath, false, ref initialFds);
+ var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 };
+ var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point
+ var changes = CreateChangeList (ref initialFds);
+
+ int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout);
+
+ if (numEvents == -1) {
+ var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ());
+ throw new IOException (errMsg);
}
}
- static void StopMonitoringDirectory (KeventData data)
+ kevent[] CreateChangeList (ref List<int> FdList)
{
- close(data.ev.ident);
+ if (FdList.Count == 0)
+ return emptyEventList;
+
+ var changes = new List<kevent> ();
+ foreach (int fd in FdList) {
+ var change = new kevent {
+
+ ident = (UIntPtr)fd,
+ filter = EventFilter.Vnode,
+ flags = EventFlags.Add | EventFlags.Enable | EventFlags.Clear,
+ fflags = FilterFlags.VNodeDelete | FilterFlags.VNodeExtend |
+ FilterFlags.VNodeRename | FilterFlags.VNodeAttrib |
+ FilterFlags.VNodeLink | FilterFlags.VNodeRevoke |
+ FilterFlags.VNodeWrite,
+ data = IntPtr.Zero,
+ udata = IntPtr.Zero
+ };
+
+ changes.Add (change);
+ }
+ FdList.Clear ();
+
+ return changes.ToArray ();
}
void Monitor ()
{
-
- while (!stop) {
- kevent ev = new kevent();
- ev.udata = IntPtr.Zero;
- kevent nullev = new kevent();
- nullev.udata = IntPtr.Zero;
- timespec ts = new timespec();
- ts.tv_sec = 0;
- ts.tv_usec = 0;
- int haveEvents;
- lock (this) {
- haveEvents = kevent (conn, ref nullev, 0, ref ev, 1, ref ts);
+ var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 };
+ var eventBuffer = new kevent[32];
+ var newFds = new List<int> ();
+ List<PathData> removeQueue = new List<PathData> ();
+ List<string> rescanQueue = new List<string> ();
+
+ while (!requestStop) {
+ var changes = CreateChangeList (ref newFds);
+
+ int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout);
+
+ if (numEvents == -1) {
+ var errMsg = String.Format ("kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ());
+ fsw.OnError (new ErrorEventArgs (new IOException (errMsg)));
}
- if (haveEvents > 0) {
- // Restart monitoring
- KeventData data = (KeventData) requests [ev.ident];
- StopMonitoringDirectory (data);
- StartMonitoringDirectory (data);
- ProcessEvent (ev);
- } else {
- System.Threading.Thread.Sleep (500);
+ if (numEvents == 0)
+ continue;
+
+ for (var i = 0; i < numEvents; i++) {
+ var kevt = eventBuffer [i];
+ var pathData = fdsDict [(int)kevt.ident];
+
+ if ((kevt.flags & EventFlags.Error) == EventFlags.Error) {
+ var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data);
+ fsw.OnError (new ErrorEventArgs (new IOException (errMsg)));
+ continue;
+ }
+
+ if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke)
+ removeQueue.Add (pathData);
+
+ else if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) {
+ if (pathData.IsDirectory)
+ rescanQueue.Add (pathData.Path);
+ else
+ PostEvent (FileAction.Modified, pathData.Path);
+ }
+
+ else if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) {
+ var newFilename = GetFilenameFromFd (pathData.Fd);
+
+ if (newFilename.StartsWith (fsw.FullPath))
+ Rename (pathData, newFilename);
+ else //moved outside of our watched dir so stop watching
+ RemoveTree (pathData);
+ }
+
+ else if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend)
+ PostEvent (FileAction.Modified, pathData.Path);
}
+
+ removeQueue.ForEach (Remove);
+ removeQueue.Clear ();
+
+ rescanQueue.ForEach (path => {
+ Scan (path, true, ref newFds);
+ });
+ rescanQueue.Clear ();
+ }
+ }
+
+ PathData Add (string path, bool postEvents, ref List<int> fds)
+ {
+ PathData pathData;
+ pathsDict.TryGetValue (path, out pathData);
+
+ if (pathData != null)
+ return pathData;
+
+ var fd = open (path, O_EVTONLY, 0);
+
+ if (fd == -1) {
+ fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+ "open() error while attempting to process path '{0}', error code = '{1}'", path, Marshal.GetLastWin32Error ()))));
+ return null;
}
- lock (this) {
- thread = null;
- stop = false;
+ try {
+ fds.Add (fd);
+
+ var attrs = File.GetAttributes (path);
+
+ pathData = new PathData {
+ Path = path,
+ Fd = fd,
+ IsDirectory = (attrs & FileAttributes.Directory) == FileAttributes.Directory
+ };
+
+ pathsDict.Add (path, pathData);
+ fdsDict.Add (fd, pathData);
+
+ if (postEvents)
+ PostEvent (FileAction.Added, path);
+
+ return pathData;
+ } catch (Exception e) {
+ close (fd);
+ fsw.OnError (new ErrorEventArgs (e));
+ return null;
}
+
}
- void ProcessEvent (kevent ev)
+ void Remove (PathData pathData)
{
- lock (this) {
- KeventData data = (KeventData) requests [ev.ident];
- if (!data.Enabled)
- return;
+ fdsDict.Remove (pathData.Fd);
+ pathsDict.Remove (pathData.Path);
+ close (pathData.Fd);
+ PostEvent (FileAction.Removed, pathData.Path);
+ }
- FileSystemWatcher fsw;
- string filename = "";
+ void RemoveTree (PathData pathData)
+ {
+ var toRemove = new List<PathData> ();
- fsw = data.FSW;
- FileAction fa = 0;
- DirectoryInfo dir = new DirectoryInfo (data.Directory);
- FileSystemInfo changedFsi = null;
+ toRemove.Add (pathData);
- try {
- foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() )
- if (data.DirEntries.ContainsKey (fsi.FullName) && (fsi is FileInfo)) {
- KeventFileData entry = (KeventFileData) data.DirEntries [fsi.FullName];
- if (entry.LastWriteTime != fsi.LastWriteTime) {
- filename = fsi.Name;
- fa = FileAction.Modified;
- data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
- if (fsw.IncludeSubdirectories && fsi is DirectoryInfo) {
- data.Directory = filename;
- requests [ev.ident] = data;
- ProcessEvent(ev);
- }
- changedFsi = fsi;
- PostEvent(filename, fsw, fa, changedFsi);
- }
- }
- } catch (Exception) {
- // The file system infos were changed while we processed them
- }
- // Deleted
- try {
- bool deleteMatched = true;
- while(deleteMatched) {
- foreach (KeventFileData entry in data.DirEntries.Values) {
- if (!File.Exists (entry.fsi.FullName) && !Directory.Exists (entry.fsi.FullName)) {
- filename = entry.fsi.Name;
- fa = FileAction.Removed;
- data.DirEntries.Remove (entry.fsi.FullName);
- changedFsi = entry.fsi;
- PostEvent(filename, fsw, fa, changedFsi);
- break;
- }
- }
- deleteMatched = false;
+ if (pathData.IsDirectory) {
+ var prefix = pathData.Path + Path.DirectorySeparatorChar;
+ foreach (var path in pathsDict.Keys)
+ if (path.StartsWith (prefix)) {
+ toRemove.Add (pathsDict [path]);
}
- } catch (Exception) {
- // The file system infos were changed while we processed them
- }
- // Added
- try {
- foreach (FileSystemInfo fsi in dir.GetFileSystemInfos())
- if (!data.DirEntries.ContainsKey (fsi.FullName)) {
- changedFsi = fsi;
- filename = fsi.Name;
- fa = FileAction.Added;
- data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
- PostEvent(filename, fsw, fa, changedFsi);
- }
- } catch (Exception) {
- // The file system infos were changed while we processed them
- }
-
+ }
+ toRemove.ForEach (Remove);
+ }
+ void Rename (PathData pathData, string newRoot)
+ {
+ var toRename = new List<PathData> ();
+ var oldRoot = pathData.Path;
+
+ toRename.Add (pathData);
+
+ if (pathData.IsDirectory) {
+ var prefix = oldRoot + Path.DirectorySeparatorChar;
+ foreach (var path in pathsDict.Keys)
+ if (path.StartsWith (prefix))
+ toRename.Add (pathsDict [path]);
}
+
+ toRename.ForEach ((pd) => {
+ var oldPath = pd.Path;
+ var newPath = newRoot + oldPath.Substring (oldRoot.Length);
+ pd.Path = newPath;
+ pathsDict.Remove (oldPath);
+ pathsDict.Add (newPath, pd);
+ });
+
+ PostEvent (FileAction.RenamedNewName, oldRoot, newRoot);
}
- private void PostEvent (string filename, FileSystemWatcher fsw, FileAction fa, FileSystemInfo changedFsi) {
- RenamedEventArgs renamed = null;
- if (fa == 0)
+ void Scan (string path, bool postEvents, ref List<int> fds)
+ {
+ if (requestStop)
return;
-
- if (fsw.IncludeSubdirectories && fa == FileAction.Added) {
- if (changedFsi is DirectoryInfo) {
- KeventData newdirdata = new KeventData ();
- newdirdata.FSW = fsw;
- newdirdata.Directory = changedFsi.FullName;
- newdirdata.FileMask = fsw.MangledFilter;
- newdirdata.IncludeSubdirs = fsw.IncludeSubdirectories;
-
- newdirdata.Enabled = true;
- lock (this) {
- StartMonitoringDirectory (newdirdata);
- }
+
+ var pathData = Add (path, postEvents, ref fds);
+
+ if (pathData == null)
+ return;
+
+ if (!pathData.IsDirectory)
+ return;
+
+ var dirsToProcess = new List<string> ();
+ dirsToProcess.Add (path);
+
+ while (dirsToProcess.Count > 0) {
+ var tmp = dirsToProcess [0];
+ dirsToProcess.RemoveAt (0);
+
+ var info = new DirectoryInfo (tmp);
+ FileSystemInfo[] fsInfos = null;
+ try {
+ fsInfos = info.GetFileSystemInfos ();
+
+ } catch (IOException) {
+ // this can happen if the directory has been deleted already.
+ // that's okay, just keep processing the other dirs.
+ fsInfos = new FileSystemInfo[0];
+ }
+
+ foreach (var fsi in fsInfos) {
+ if ((fsi.Attributes & FileAttributes.Directory) == FileAttributes.Directory && !fsw.IncludeSubdirectories)
+ continue;
+
+ if ((fsi.Attributes & FileAttributes.Directory) != FileAttributes.Directory && !fsw.Pattern.IsMatch (fsi.FullName))
+ continue;
+
+ var currentPathData = Add (fsi.FullName, postEvents, ref fds);
+
+ if (currentPathData != null && currentPathData.IsDirectory)
+ dirsToProcess.Add (fsi.FullName);
}
}
-
- if (!fsw.Pattern.IsMatch(filename, true))
+ }
+
+ void PostEvent (FileAction action, string path, string newPath = null)
+ {
+ RenamedEventArgs renamed = null;
+
+ if (action == 0)
return;
+ // only post events that match filter pattern. check both old and new paths for renames
+ if (!fsw.Pattern.IsMatch (path) && (newPath == null || !fsw.Pattern.IsMatch (newPath)))
+ return;
+
+ if (action == FileAction.RenamedNewName)
+ renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, "", newPath, path);
+
lock (fsw) {
- if (changedFsi.FullName.StartsWith (fsw.FullPath, StringComparison.Ordinal)) {
- if (fsw.FullPath.EndsWith ("/", StringComparison.Ordinal)) {
- filename = changedFsi.FullName.Substring (fsw.FullPath.Length);
- } else {
- filename = changedFsi.FullName.Substring (fsw.FullPath.Length + 1);
- }
- }
- fsw.DispatchEvents (fa, filename, ref renamed);
+ fsw.DispatchEvents (action, path, ref renamed);
+
if (fsw.Waiting) {
fsw.Waiting = false;
System.Threading.Monitor.PulseAll (fsw);
}
}
+ private string GetFilenameFromFd (int fd)
+ {
+ var sb = new StringBuilder (__DARWIN_MAXPATHLEN);
+
+ if (fcntl (fd, F_GETPATH, sb) != -1) {
+ if (fixupPath != null)
+ sb.Replace (fixupPath, fsw.FullPath, 0, fixupPath.Length); // see Setup()
+ return sb.ToString ();
+ } else {
+ fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+ "fcntl() error while attempting to get path for fd '{0}', error code = '{1}'", fd, Marshal.GetLastWin32Error ()))));
+ return String.Empty;
+ }
+ }
+
+ const int O_EVTONLY = 0x8000;
+ const int F_GETPATH = 50;
+ const int __DARWIN_MAXPATHLEN = 1024;
+ static readonly kevent[] emptyEventList = new System.IO.kevent[0];
+
+ FileSystemWatcher fsw;
+ int conn;
+ Thread thread;
+ volatile bool requestStop = false;
+ AutoResetEvent startedEvent = new AutoResetEvent (false);
+ bool started = false;
+ bool failedInit = false;
+ object stateLock = new object ();
+
+ readonly Dictionary<string, PathData> pathsDict = new Dictionary<string, PathData> ();
+ readonly Dictionary<int, PathData> fdsDict = new Dictionary<int, PathData> ();
+ string fixupPath = null;
+
+ [DllImport ("libc", EntryPoint="fcntl", CharSet=CharSet.Auto, SetLastError=true)]
+ static extern int fcntl (int file_names_by_descriptor, int cmd, StringBuilder sb);
+
+ [DllImport ("libc")]
+ extern static int open (string path, int flags, int mode_t);
+
[DllImport ("libc")]
- extern static int open(string path, int flags, int mode_t);
-
+ extern static int close (int fd);
+
[DllImport ("libc")]
- extern static int close(int fd);
+ extern static int kqueue ();
[DllImport ("libc")]
- extern static int kqueue();
+ extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time);
+ }
+
+ class KeventWatcher : IFileWatcher
+ {
+ static bool failed;
+ static KeventWatcher instance;
+ static Hashtable watches; // <FileSystemWatcher, KqueueMonitor>
+
+ private KeventWatcher ()
+ {
+ }
+
+ // Locked by caller
+ public static bool GetInstance (out IFileWatcher watcher)
+ {
+ if (failed == true) {
+ watcher = null;
+ return false;
+ }
+
+ if (instance != null) {
+ watcher = instance;
+ return true;
+ }
+
+ watches = Hashtable.Synchronized (new Hashtable ());
+ var conn = kqueue();
+ if (conn == -1) {
+ failed = true;
+ watcher = null;
+ return false;
+ }
+ close (conn);
+
+ instance = new KeventWatcher ();
+ watcher = instance;
+ return true;
+ }
+
+ public void StartDispatching (FileSystemWatcher fsw)
+ {
+ KqueueMonitor monitor;
+
+ if (watches.ContainsKey (fsw)) {
+ monitor = (KqueueMonitor)watches [fsw];
+ } else {
+ monitor = new KqueueMonitor (fsw);
+ watches.Add (fsw, monitor);
+ }
+
+ monitor.Start ();
+ }
+
+ public void StopDispatching (FileSystemWatcher fsw)
+ {
+ KqueueMonitor monitor = (KqueueMonitor)watches [fsw];
+ if (monitor == null)
+ return;
+
+ monitor.Stop ();
+ }
+
+ [DllImport ("libc")]
+ extern static int close (int fd);
[DllImport ("libc")]
- extern static int kevent(int kqueue, ref kevent ev, int nchanges, ref kevent evtlist, int nevents, ref timespec ts);
+ extern static int kqueue ();
}
}
Compile (pattern);
}
- // OSX has a retarded case-insensitive yet case-aware filesystem
+ // OSX has a case-insensitive yet case-aware filesystem
// so we need a overload in here for the Kqueue watcher
public bool IsMatch (string text, bool ignorecase)
{
bool match = String.Compare (pattern, text, ignorecase) == 0;
if (match)
return true;
-
- // This is a special case for FSW. It needs to match e.g. subdir/file.txt
- // when the pattern is "file.txt"
- int idx = text.LastIndexOf ('/');
- if (idx == -1)
- return false;
- idx++;
- if (idx == text.Length)
- return false;
-
- return (String.Compare (pattern, text.Substring (idx), ignorecase) == 0);
}
+
+ // This is a special case for FSW. It needs to match e.g. subdir/file.txt
+ // when the pattern is "file.txt"
+ var fileName = Path.GetFileName (text);
+
+ if (!hasWildcard)
+ return (String.Compare (pattern, fileName, ignorecase) == 0);
+
- return Match (ops, text, 0);
+ return Match (ops, fileName, 0);
}
public bool IsMatch (string text)
snd_pcm_hw_params_free (hw_param);
if (handle != IntPtr.Zero)
snd_pcm_close (handle);
+ sw_param = IntPtr.Zero;
+ hw_param = IntPtr.Zero;
handle = IntPtr.Zero;
}
Console.WriteLine ("failed to alloc Alsa sw param struct");
}
- if (hw_param != IntPtr.Zero)
+ if (hw_param != IntPtr.Zero) {
snd_pcm_hw_params_free (hw_param); // free hw params
- if (sw_param != IntPtr.Zero)
+ hw_param = IntPtr.Zero;
+ }
+ if (sw_param != IntPtr.Zero) {
snd_pcm_sw_params_free (sw_param); // free sw params
+ sw_param = IntPtr.Zero;
+ }
return alsa_err == 0;
}
curSocket.EndConnect (ares);
} catch (SocketException se) {
SocketError = se.SocketErrorCode;
+ } catch (ObjectDisposedException) {
+ SocketError = SocketError.OperationAborted;
} finally {
OnCompleted (this);
}
#endif
}
+#if NET_4_5
+ [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")]
+ public Socket (SocketType socketType, ProtocolType protocolType)
+ : this (AddressFamily.InterNetwork, socketType, protocolType)
+ {
+ }
+#endif
+
~Socket ()
{
Dispose (false);
if (fileName == null)
throw new ArgumentNullException ("fileName");
- WebRequest request = null;
try {
SetBusy ();
cts = new CancellationTokenSource ();
- request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
- var result = await UploadFileTaskAsyncCore (request, method, fileName, cts.Token).ConfigureAwait (false);
+
+ var result = await UploadFileTaskAsyncCore (address, method, fileName, cts.Token).ConfigureAwait (false);
OnUploadFileCompleted (new UploadFileCompletedEventArgs (result, null, false, null));
return result;
} catch (WebException ex) {
OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, false, null));
throw;
} catch (OperationCanceledException) {
- if (request != null)
- request.Abort ();
OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, null, true, null));
throw;
} catch (Exception ex) {
}
}
- async Task<byte[]> UploadFileTaskAsyncCore (WebRequest request, string method,
- string fileName, CancellationToken token)
+ async Task<byte[]> UploadFileTaskAsyncCore (Uri address, string method, string fileName, CancellationToken token)
{
token.ThrowIfCancellationRequested ();
Stream reqStream = null;
Stream fStream = null;
WebResponse response = null;
+ WebRequest request = null;
fileName = Path.GetFullPath (fileName);
+ try {
+ request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
+ } catch (OperationCanceledException) {
+ }
+
try {
fStream = File.OpenRead (fileName);
token.ThrowIfCancellationRequested ();
Path.GetFileName (fileName), fileCType);
byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
ms.Write (partHeadersBytes, 0, partHeadersBytes.Length);
- await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
+ var msLength = (int)ms.Position;
+ ms.Seek (0, SeekOrigin.Begin);
+ await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false);
}
}
int nread;
ms.WriteByte ((byte) '-');
ms.WriteByte ((byte) '\r');
ms.WriteByte ((byte) '\n');
- await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
+ var msLength = (int)ms.Position;
+ ms.Seek (0, SeekOrigin.Begin);
+ await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false);
}
}
reqStream.Close ();
webClient.UploadFileAsync (uri, "PUT", tempFile);
});
}
+
+ [Test]
+ public void UploadFileAsyncContentType ()
+ {
+ var serverUri = "http://localhost:13370/";
+ var filename = Path.GetTempFileName ();
+
+ HttpListener listener = new HttpListener ();
+ listener.Prefixes.Add (serverUri);
+ listener.Start ();
+
+ using (var client = new WebClient ())
+ {
+ client.UploadFileTaskAsync (new Uri (serverUri), filename);
+ var request = listener.GetContext ().Request;
+
+ var expected = "multipart/form-data; boundary=------------";
+ Assert.AreEqual (expected.Length + 15, request.ContentType.Length);
+ Assert.AreEqual (expected, request.ContentType.Substring (0, expected.Length));
+ }
+ listener.Close ();
+ }
#endif
#if NET_4_0
--- /dev/null
+#!/bin/sh
+
+SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+export MONO_PATH=${MONO_PATH:-$SCRIPT_PATH/../lib/net_4_5/}
+
+TZ_FAILS=0
+TZ_COUNT=0
+FORMAT="%a %b %d %T %Y"
+
+for tz in $(cd /usr/share/zoneinfo/; find * -type f -print); do
+ TZ_COUNT=$(expr $TZ_COUNT + 1)
+ SYS_DATETIME=$(date -ju -f "$FORMAT" "$(TZ=$tz date "+$FORMAT")" "+%s")
+ CS_DATETIME=$(TZ=$tz csharp -e '(int)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;')
+ DIFF=$(expr $SYS_DATETIME - $CS_DATETIME)
+ if [ "$DIFF" -gt "5" ] || [ "$DIFF" -lt "-5" ]; then
+ TZ_FAILS=$(expr $TZ_FAILS + 1)
+ echo ""
+ echo "DateTime.Now failed with timezone: $tz"
+ echo " System: $(date -ju -f "%s" "$SYS_DATETIME" "+%Y-%m-%d %T")"
+ echo " DateTime.Now: $(date -ju -f "%s" "$CS_DATETIME" "+%Y-%m-%d %T")"
+ fi
+ echo ".\c"
+done
+echo ""
+echo "DateTime.Now failed with $TZ_FAILS of $TZ_COUNT timezones."
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if NET_4_0
-
using System.Runtime.CompilerServices;
namespace System
#elif NET_4_0
[TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
#endif
- public class InvalidTimeZoneException : Exception
+#if NET_4_0
+ public
+#endif
+ class InvalidTimeZoneException : Exception
{
public InvalidTimeZoneException () : base ()
{}
{}
}
}
-
-#endif
return DateTime.SpecifyKind (DateTime.MinValue, DateTimeKind.Local);
}
- DateTime local = DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local);
- DaylightTime dlt = GetDaylightChanges (time.Year);
- if (dlt.Delta.Ticks == 0)
- return DateTime.SpecifyKind (local, DateTimeKind.Local);
-
- // FIXME: check all of the combination of
- // - basis: local-based or UTC-based
- // - hemisphere: Northern or Southern
- // - offset: positive or negative
-
- // PST should work fine here.
- if (local < dlt.End && dlt.End.Subtract (dlt.Delta) <= local)
- return DateTime.SpecifyKind (local, DateTimeKind.Local);
-
- TimeSpan localOffset = GetUtcOffset (local);
- return DateTime.SpecifyKind (time.Add (localOffset), DateTimeKind.Local);
+ return DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local);
}
public virtual DateTime ToUniversalTime (DateTime time)
// A yearwise cache of DaylightTime.
private Dictionary<int, DaylightTime> m_CachedDaylightChanges = new Dictionary<int, DaylightTime> (1);
- // the offset when daylightsaving is not on (in ticks)
- private long m_ticksOffset;
-
- // the offset when daylightsaving is not on.
- [NonSerialized]
- private TimeSpan utcOffsetWithOutDLS;
-
- // the offset when daylightsaving is on.
- [NonSerialized]
- private TimeSpan utcOffsetWithDLS;
-
internal enum TimeZoneData
{
DaylightSavingStartIdx,
m_standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]);
m_daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]);
- m_ticksOffset = data[(int)TimeZoneData.UtcOffsetIdx];
-
DaylightTime dlt = GetDaylightTimeFromData (data);
m_CachedDaylightChanges.Add (now.Year, dlt);
OnDeserialization (dlt);
if (time.Kind == DateTimeKind.Utc)
return TimeSpan.Zero;
- if (IsDaylightSavingTime (time) && !IsAmbiguousTime (time))
- return utcOffsetWithDLS;
-
- return utcOffsetWithOutDLS;
- }
-
- private bool IsAmbiguousTime (DateTime time)
- {
- if (time.Kind == DateTimeKind.Utc)
- return false;
-
- DaylightTime changes = GetDaylightChanges (time.Year);
-
- return time < changes.End && time >= changes.End - changes.Delta;
+ return TimeZoneInfo.Local.GetUtcOffset (time);
}
void IDeserializationCallback.OnDeserialization (object sender)
} else
this_year = dlt.Start.Year;
- utcOffsetWithOutDLS = new TimeSpan (m_ticksOffset);
- utcOffsetWithDLS = new TimeSpan (m_ticksOffset + dlt.Delta.Ticks);
this_year_dlt = dlt;
}
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if NET_4_0
using System.Runtime.CompilerServices;
#elif NET_4_0
[TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
#endif
- public class TimeZoneNotFoundException : Exception
+#if NET_4_0
+ public
+#endif
+ class TimeZoneNotFoundException : Exception
{
public TimeZoneNotFoundException () : base ()
{}
{}
}
}
-
-#endif
}
}
+ int workerThreads;
+ int completionPortThreads;
Task[] tasks;
const int max = 6;
[SetUp]
public void Setup()
{
+ ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
+ ThreadPool.SetMinThreads (1, 1);
+
tasks = new Task[max];
}
+ [TearDown]
+ public void Teardown()
+ {
+ ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
+ }
+
void InitWithDelegate(Action action)
{
for (int i = 0; i < max; i++) {
{
ParallelTestHelper.Repeat (delegate {
var evt = new ManualResetEventSlim ();
- var t = Task.Factory.StartNew (() => evt.Wait (5000));
+ var monitor = new object ();
+ int finished = 0;
+ var t = Task.Factory.StartNew (delegate {
+ var r = evt.Wait (5000);
+ lock (monitor) {
+ finished ++;
+ Monitor.Pulse (monitor);
+ }
+ return r;
+ });
var cntd = new CountdownEvent (2);
var cntd2 = new CountdownEvent (2);
bool r1 = false, r2 = false;
- ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
- ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
-
+ ThreadPool.QueueUserWorkItem (delegate {
+ cntd.Signal ();
+ r1 = t.Wait (1000) && t.Result;
+ cntd2.Signal ();
+ lock (monitor) {
+ finished ++;
+ Monitor.Pulse (monitor);
+ }
+ });
+ ThreadPool.QueueUserWorkItem (delegate {
+ cntd.Signal ();
+ r2 = t.Wait (1000) && t.Result;
+ cntd2.Signal ();
+ lock (monitor) {
+ finished ++;
+ Monitor.Pulse (monitor);
+ }
+ });
Assert.IsTrue (cntd.Wait (2000), "#1");
evt.Set ();
Assert.IsTrue (cntd2.Wait (2000), "#2");
Assert.IsTrue (r1, "r1");
Assert.IsTrue (r2, "r2");
+
+ // Wait for everything to finish to avoid overloading the tpool
+ lock (monitor) {
+ while (true) {
+ if (finished == 3)
+ break;
+ else
+ Monitor.Wait (monitor);
+ }
+ }
}, 10);
}
export HOST_CC
endif
-if JIT_SUPPORTED
if !SHARED_MONO
static_libs= \
$(top_builddir)/mono/metadata/libmonoruntime-static.la \
else
runtime_lib=../mini/$(LIBMONO_LA)
endif
-else
-runtime_lib=../interpreter/libmint.la
-endif
if DISABLE_EXECUTABLES
bin_PROGRAMS =
}
}
break;
- case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+ case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
+ guint8 *ref_bitmap;
+
real_size = 0;
for (i = 0; i < top; i++) {
gint32 align;
* There must be info about all the fields in a type if it
* uses explicit layout.
*/
-
if (mono_field_is_deleted (field))
continue;
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
*/
real_size = MAX (real_size, size + field->offset);
}
+
+ if (class->has_references) {
+ ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
+
+ /* Check for overlapping reference and non-reference fields */
+ for (i = 0; i < top; i++) {
+ MonoType *ftype;
+
+ field = &class->fields [i];
+
+ if (mono_field_is_deleted (field))
+ continue;
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+ continue;
+ ftype = mono_type_get_underlying_type (field->type);
+ if (MONO_TYPE_IS_REFERENCE (ftype))
+ ref_bitmap [field->offset / sizeof (gpointer)] = 1;
+ }
+ for (i = 0; i < top; i++) {
+ field = &class->fields [i];
+
+ if (mono_field_is_deleted (field))
+ continue;
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+ continue;
+
+ // FIXME: Too much code does this
+#if 0
+ if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
+ char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+ }
+#endif
+ }
+ g_free (ref_bitmap);
+ }
+
class->instance_size = MAX (real_size, class->instance_size);
if (class->instance_size & (class->min_align - 1)) {
class->instance_size += class->min_align - 1;
}
break;
}
+ }
if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
/*
static gboolean in_sigint;
-MONO_SIGNAL_HANDLER_FUNC (static, sigint_handler, (int signo))
+MONO_SIG_HANDLER_FUNC (static, sigint_handler)
{
int save_errno;
MONO_ARCH_SAVE_REGS;
static struct sigaction save_sigcont, save_sigint, save_sigwinch;
-MONO_SIGNAL_HANDLER_FUNC (static, sigcont_handler, (int signo, void *the_siginfo, void *data))
+MONO_SIG_HANDLER_FUNC (static, sigcont_handler)
{
int unused;
// Ignore error, there is not much we can do in the sigcont handler.
if (save_sigcont.sa_sigaction != NULL &&
save_sigcont.sa_sigaction != (void *)SIG_DFL &&
save_sigcont.sa_sigaction != (void *)SIG_IGN)
- (*save_sigcont.sa_sigaction) (signo, the_siginfo, data);
+ (*save_sigcont.sa_sigaction) (MONO_SIG_HANDLER_PARAMS);
}
-MONO_SIGNAL_HANDLER_FUNC (static, sigwinch_handler, (int signo, void *the_siginfo, void *data))
+MONO_SIG_HANDLER_FUNC (static, sigwinch_handler)
{
int dims = terminal_get_dimensions ();
if (dims != -1)
if (save_sigwinch.sa_sigaction != NULL &&
save_sigwinch.sa_sigaction != (void *)SIG_DFL &&
save_sigwinch.sa_sigaction != (void *)SIG_IGN)
- (*save_sigwinch.sa_sigaction) (signo, the_siginfo, data);
+ (*save_sigwinch.sa_sigaction) (MONO_SIG_HANDLER_PARAMS);
}
/*
}
#if 0
-static void
-collect_faulted_cards (void)
-{
-#define CARD_PAGES (CARD_COUNT_IN_BYTES / 4096)
- int i, count = 0;
- unsigned char faulted [CARD_PAGES] = { 0 };
- mincore (sgen_cardtable, CARD_COUNT_IN_BYTES, faulted);
-
- for (i = 0; i < CARD_PAGES; ++i) {
- if (faulted [i])
- ++count;
- }
-
- printf ("TOTAL card pages %d faulted %d\n", CARD_PAGES, count);
-}
-
void
sgen_card_table_dump_obj_card (char *object, size_t size, void *dummy)
{
static long long time_major_sweep = 0;
static long long time_major_fragment_creation = 0;
+static long long time_max = 0;
+
static SGEN_TV_DECLARE (time_major_conc_collection_start);
static SGEN_TV_DECLARE (time_major_conc_collection_end);
if (inited)
return;
+ mono_counters_register ("Collection max time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME | MONO_COUNTER_MONOTONIC, &time_max);
+
mono_counters_register ("Minor fragment clear", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pre_collection_fragment_clear);
mono_counters_register ("Minor pinning", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pinning);
mono_counters_register ("Minor scan remembered set", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_scan_remsets);
sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish)
{
TV_DECLARE (gc_end);
+ TV_DECLARE (gc_total_start);
+ TV_DECLARE (gc_total_end);
GGTimingInfo infos [2];
int overflow_generation_to_collect = -1;
int oldest_generation_collected = generation_to_collect;
sgen_stop_world (generation_to_collect);
+ TV_GETTIME (gc_total_start);
+
if (concurrent_collection_in_progress) {
if (major_update_or_finish_concurrent_collection (wait_to_finish && generation_to_collect == GENERATION_OLD)) {
oldest_generation_collected = GENERATION_OLD;
done:
g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
+ TV_GETTIME (gc_total_end);
+ time_max = MAX (time_max, TV_ELAPSED (gc_total_start, gc_total_end));
+
sgen_restart_world (oldest_generation_collected, infos);
mono_profiler_gc_event (MONO_GC_EVENT_END, generation_to_collect);
#include "utils/mono-counters.h"
#include "metadata/sgen-gc.h"
+#include "utils/mono-mmap.h"
#include "utils/lock-free-alloc.h"
#include "metadata/sgen-memory-governor.h"
8, 16, 24, 32, 40, 48, 64, 80,
96, 128, 160, 192, 224, 248, 296, 320,
384, 448, 504, 528, 584, 680, 816, 1088,
- 1360, 2040, 2336, 2728, 3272, 4088, 5456, 8184 };
+ 1360, 2044, 2336, 2728, 3272, 4092, 5456, 8188 };
#else
static const int allocator_sizes [] = {
8, 16, 24, 32, 40, 48, 64, 80,
#define NUM_ALLOCATORS (sizeof (allocator_sizes) / sizeof (int))
+static int allocator_block_sizes [NUM_ALLOCATORS];
+
static MonoLockFreeAllocSizeClass size_classes [NUM_ALLOCATORS];
static MonoLockFreeAllocator allocators [NUM_ALLOCATORS];
+#ifdef HEAVY_STATISTICS
+static int allocator_sizes_stats [NUM_ALLOCATORS];
+#endif
+
+static size_t
+block_size (size_t slot_size)
+{
+ static int pagesize = -1;
+
+ int size;
+
+ if (pagesize == -1)
+ pagesize = mono_pagesize ();
+
+ for (size = pagesize; size < LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) {
+ if (slot_size * 2 <= LOCK_FREE_ALLOC_SB_USABLE_SIZE (size))
+ return size;
+ }
+ return LOCK_FREE_ALLOC_SB_MAX_SIZE;
+}
+
/*
* Find the allocator index for memory chunks that can contain @size
* objects.
int slot;
g_assert (type >= 0 && type < INTERNAL_MEM_MAX);
+ g_assert (size <= allocator_sizes [NUM_ALLOCATORS - 1]);
slot = index_for_size (size);
g_assert (slot >= 0);
} else {
index = index_for_size (size);
+#ifdef HEAVY_STATISTICS
+ ++ allocator_sizes_stats [index];
+#endif
+
p = mono_lock_free_alloc (&allocators [index]);
if (!p)
sgen_assert_memory_alloc (NULL, size, description_for_type (type));
if (size > allocator_sizes [NUM_ALLOCATORS - 1])
sgen_free_os_memory (addr, size, SGEN_ALLOC_INTERNAL);
else
- mono_lock_free_free (addr);
+ mono_lock_free_free (addr, block_size (size));
MONO_GC_INTERNAL_DEALLOC ((mword)addr, size, type);
}
void*
sgen_alloc_internal (int type)
{
- int index = fixed_type_allocator_indexes [type];
- int size = allocator_sizes [index];
+ int index, size;
void *p;
+
+ index = fixed_type_allocator_indexes [type];
g_assert (index >= 0 && index < NUM_ALLOCATORS);
+
+#ifdef HEAVY_STATISTICS
+ ++ allocator_sizes_stats [index];
+#endif
+
+ size = allocator_sizes [index];
+
p = mono_lock_free_alloc (&allocators [index]);
memset (p, 0, size);
index = fixed_type_allocator_indexes [type];
g_assert (index >= 0 && index < NUM_ALLOCATORS);
- mono_lock_free_free (addr);
+ mono_lock_free_free (addr, allocator_block_sizes [index]);
if (MONO_GC_INTERNAL_DEALLOC_ENABLED ()) {
int size G_GNUC_UNUSED = allocator_sizes [index];
void
sgen_report_internal_mem_usage (void)
{
- /* FIXME: implement */
- printf ("not implemented yet\n");
+ int i G_GNUC_UNUSED;
+#ifdef HEAVY_STATISTICS
+ printf ("size -> # allocations\n");
+ for (i = 0; i < NUM_ALLOCATORS; ++i)
+ printf ("%d -> %d\n", allocator_sizes [i], allocator_sizes_stats [i]);
+#endif
}
void
sgen_init_internal_allocator (void)
{
- int i;
+ int i, size;
for (i = 0; i < INTERNAL_MEM_MAX; ++i)
fixed_type_allocator_indexes [i] = -1;
for (i = 0; i < NUM_ALLOCATORS; ++i) {
- mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i]);
+ allocator_block_sizes [i] = block_size (allocator_sizes [i]);
+ mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i], allocator_block_sizes [i]);
mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i]);
}
+
+ for (size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) {
+ int max_size = LOCK_FREE_ALLOC_SB_USABLE_SIZE (size) / 2;
+ /*
+ * we assert that allocator_sizes contains the biggest possible object size
+ * per block (4K => 4080 / 2 = 2040, 8k => 8176 / 2 = 4088, 16k => 16368 / 2 = 8184 on 64bits),
+ * so that we do not get different block sizes for sizes that should go to the same one
+ */
+ g_assert (allocator_sizes [index_for_size (max_size)] == max_size);
+ }
}
#endif
/**/
static mword allocated_heap;
static mword total_alloc = 0;
+static mword total_alloc_max = 0;
/* GC triggers. */
static mword sgen_memgov_available_free_space (void);
-static mword
-double_to_mword_with_saturation (double value)
-{
- if (value >= (double)MWORD_MAX_VALUE)
- return MWORD_MAX_VALUE;
- return (mword)value;
-}
-
/* GC trigger heuristics. */
static void
sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
{
- size_t num_major_sections, num_major_sections_saved;
- mword los_memory_saved, new_major, new_heap_size, save_target, allowance_target;
+ size_t num_major_sections;
+ mword new_major, new_heap_size, allowance_target;
if (overwrite)
g_assert (need_calculate_minor_collection_allowance);
num_major_sections = major_collector.get_num_major_sections ();
- num_major_sections_saved = MAX (last_collection_old_num_major_sections - num_major_sections, 0);
- los_memory_saved = MAX (last_collection_old_los_memory_usage - last_collection_los_memory_usage, 1);
-
new_major = num_major_sections * major_collector.section_size;
new_heap_size = new_major + last_collection_los_memory_usage;
- save_target = (mword)((new_major + last_collection_los_memory_usage) * SGEN_DEFAULT_SAVE_TARGET_RATIO);
-
/*
- * We aim to allow the allocation of as many sections as is
- * necessary to reclaim save_target sections in the next
- * collection. We assume the collection pattern won't change.
- * In the last cycle, we had num_major_sections_saved for
- * minor_collection_sections_alloced. Assuming things won't
- * change, this must be the same ratio as save_target for
- * allowance_target, i.e.
- *
- * num_major_sections_saved save_target
- * --------------------------------- == ----------------
- * minor_collection_sections_alloced allowance_target
- *
- * hence:
+ * We allow the heap to grow by one third its current size before we start the next
+ * major collection.
*/
- allowance_target = double_to_mword_with_saturation ((double)save_target * (double)(minor_collection_sections_alloced * major_collector.section_size + last_collection_los_memory_alloced) / (double)(num_major_sections_saved * major_collector.section_size + los_memory_saved));
+ allowance_target = new_heap_size / 3;
- minor_collection_allowance = MAX (MIN (allowance_target, num_major_sections * major_collector.section_size + los_memory_usage), MIN_MINOR_COLLECTION_ALLOWANCE);
+ minor_collection_allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
if (new_heap_size + minor_collection_allowance > soft_heap_limit) {
if (new_heap_size > soft_heap_limit)
SGEN_ATOMIC_ADD_P (total_alloc, size);
if (flags & SGEN_ALLOC_HEAP)
MONO_GC_HEAP_ALLOC ((mword)ptr, size);
+ total_alloc_max = MAX (total_alloc_max, total_alloc);
}
return ptr;
}
SGEN_ATOMIC_ADD_P (total_alloc, size);
if (flags & SGEN_ALLOC_HEAP)
MONO_GC_HEAP_ALLOC ((mword)ptr, size);
+ total_alloc_max = MAX (total_alloc_max, total_alloc);
}
return ptr;
}
SGEN_ATOMIC_ADD_P (total_alloc, -(gssize)size);
if (flags & SGEN_ALLOC_HEAP)
MONO_GC_HEAP_FREE ((mword)addr, size);
+ total_alloc_max = MAX (total_alloc_max, total_alloc);
}
int64_t
debug_print_allowance = debug_allowance;
minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
+ mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, &total_alloc);
+ mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, &total_alloc_max);
+
if (max_heap == 0)
return;
}
/* LOCKING: assumes the GC lock is held (by the stopping thread) */
-MONO_SIGNAL_HANDLER_FUNC (static, suspend_handler, (int sig, siginfo_t *siginfo, void *context))
+MONO_SIG_HANDLER_FUNC (static, suspend_handler)
{
/*
* The suspend signal handler potentially uses syscalls that
* must restore those to the values they had when we
* interrupted.
*/
-
SgenThreadInfo *info;
int old_errno = errno;
int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
+ MONO_SIG_HANDLER_GET_CONTEXT;
info = mono_thread_info_current ();
- suspend_thread (info, context);
+ suspend_thread (info, ctx);
mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
errno = old_errno;
}
-MONO_SIGNAL_HANDLER_FUNC (static, restart_handler, (int sig))
+MONO_SIG_HANDLER_FUNC (static, restart_handler)
{
SgenThreadInfo *info;
int old_errno = errno;
#include <glib.h>
#include <string.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-
-#include <sys/types.h>
#ifdef HOST_WIN32
#include <ws2tcpip.h>
#else
#include <netdb.h>
#include <arpa/inet.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <sys/types.h>
#include <mono/metadata/object.h>
#include <mono/io-layer/io-layer.h>
static MonoClass *socket_async_call_klass;
static MonoClass *process_async_call_klass;
+static GPtrArray *threads;
+mono_mutex_t threads_lock;
static GPtrArray *wsqs;
mono_mutex_t wsqs_lock;
static gboolean suspended;
gint8 nthreads_diff;
} SamplesHistory;
+/*
+ * returns :
+ * - 1 if the number of threads should increase
+ * - 0 if it should not change
+ * - -1 if it should decrease
+ * - -2 in case of error
+ */
static gint8
monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *history, ThreadPool *tp)
{
int i;
gint8 decision;
gint16 cur, max = 0;
+ gboolean all_waitsleepjoin;
+ MonoInternalThread *thread;
/*
* The following heuristic tries to approach the optimal number of threads to maximize jobs throughput. To
history [cur].nthreads_diff = 1;
decision = 2;
} else {
- max = cur == 0 ? 1 : 0;
- for (i = 0; i < *history_size; i++) {
- if (i == cur)
- continue;
- if (history [i].nexecuted > history [max].nexecuted)
- max = i;
+ mono_mutex_lock (&threads_lock);
+ if (threads == NULL) {
+ mono_mutex_unlock (&threads_lock);
+ return -2;
+ }
+ all_waitsleepjoin = TRUE;
+ for (i = 0; i < threads->len; ++i) {
+ thread = g_ptr_array_index (threads, i);
+ if (!(thread->state & ThreadState_WaitSleepJoin)) {
+ all_waitsleepjoin = FALSE;
+ break;
+ }
}
+ mono_mutex_unlock (&threads_lock);
- if (history [cur].nexecuted >= history [max].nexecuted) {
- /* we improved the situation, let's continue ! */
- history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? 1 : -1;
- decision = 3;
+ if (all_waitsleepjoin) {
+ /* we might be in a condition of starvation/deadlock with tasks waiting for each others */
+ history [cur].nthreads_diff = 1;
+ decision = 5;
} else {
- /* we made it worse, let's return to previous situation */
- history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? -1 : 1;
- decision = 4;
+ max = cur == 0 ? 1 : 0;
+ for (i = 0; i < *history_size; i++) {
+ if (i == cur)
+ continue;
+ if (history [i].nexecuted > history [max].nexecuted)
+ max = i;
+ }
+
+ if (history [cur].nexecuted >= history [max].nexecuted) {
+ /* we improved the situation, let's continue ! */
+ history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? 1 : -1;
+ decision = 3;
+ } else {
+ /* we made it worse, let's return to previous situation */
+ history [cur].nthreads_diff = history [cur].nthreads >= history [max].nthreads ? -1 : 1;
+ decision = 4;
+ }
}
}
if (suspended)
continue;
+ /* threadpool is cleaning up */
+ if (async_tp.pool_status == 2 || async_io_tp.pool_status == 2)
+ break;
+
switch (monitor_state) {
case MONITOR_STATE_AWAKE:
num_waiting_iterations = 0;
} else {
gint8 nthreads_diff = monitor_heuristic (¤t, &history_size, history, tp);
- if (nthreads_diff > 0)
+ if (nthreads_diff == 1)
threadpool_start_thread (tp);
- else if (nthreads_diff < 0)
+ else if (nthreads_diff == -1)
threadpool_kill_thread (tp);
}
}
async_call_klass = mono_class_from_name (mono_defaults.corlib, "System", "MonoAsyncCall");
g_assert (async_call_klass);
+ mono_mutex_init (&threads_lock);
+ threads = g_ptr_array_sized_new (thread_count);
+ g_assert (threads);
+
mono_mutex_init_recursive (&wsqs_lock);
wsqs = g_ptr_array_sized_new (MAX (100 * cpu_count, thread_count));
threadpool_kill_idle_threads (&async_tp);
threadpool_free_queue (&async_tp);
}
+
+ if (threads) {
+ mono_mutex_lock (&threads_lock);
+ if (threads)
+ g_ptr_array_free (threads, FALSE);
+ threads = NULL;
+ mono_mutex_unlock (&threads_lock);
+ }
if (wsqs) {
mono_mutex_lock (&wsqs_lock);
{
gint n;
guint32 stack_size;
+ MonoInternalThread *thread;
stack_size = (!tp->is_io) ? 0 : SMALL_STACK;
while (!mono_runtime_is_shutting_down () && (n = tp->nthreads) < tp->max_threads) {
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounter_update_value (tp->pc_nthreads, TRUE, 1);
#endif
- mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size);
+ thread = mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size);
+ if (!tp->is_io) {
+ mono_mutex_lock (&threads_lock);
+ g_assert (threads != NULL);
+ g_ptr_array_add (threads, thread);
+ mono_mutex_unlock (&threads_lock);
+ }
return TRUE;
}
}
if (tp_finish_func)
tp_finish_func (tp_hooks_user_data);
+
+ if (!tp->is_io) {
+ if (threads) {
+ mono_mutex_lock (&threads_lock);
+ if (threads)
+ g_ptr_array_remove_fast (threads, mono_thread_current ()->internal_thread);
+ mono_mutex_unlock (&threads_lock);
+ }
+ }
+
return;
}
}
endif
endif
-if JIT_SUPPORTED
-
if SUPPORT_SGEN
sgen_binaries = mono-sgen
sgen_libraries = libmonosgen-2.0.la
endif
endif
-endif
-
mono_boehm_SOURCES = \
main.c
@echo "const char *build_date = \"`date`\";" > buildver-boehm.h
mono_boehm-main.$(OBJEXT): buildver-boehm.h
main.c: buildver-boehm.h
-
+
endif
if DISABLE_EXECUTABLES
s390x_sources = \
mini-s390x.c \
mini-s390x.h \
+ support-s390x.h \
exceptions-s390x.c \
tramp-s390x.c
pkgconfigdir = $(libdir)/pkgconfig
-if JIT_SUPPORTED
BUILT_SOURCES = version.h $(arch_built)
-else
-BUILT_SOURCES = version.h
-endif
CLEANFILES= $(BUILT_SOURCES) *.exe *.dll
EXTRA_DIST = TestDriver.cs ldscript ldscript.mono \
if (info && !has_nullable) {
/* Supported by the dynamic runtime-invoke wrapper */
skip = TRUE;
- g_free (info);
}
+ if (info)
+ mono_arch_dyn_call_free (info);
}
#endif
plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
ji = plt_entry->ji;
- if (acfg->llvm) {
- /*
- * If the target is directly callable, alias the plt symbol to point to
- * the method code.
- * FIXME: Use this to simplify emit_and_reloc_code ().
- * FIXME: Avoid the got slot.
- * FIXME: Add support to the binary writer.
- */
- if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) {
- MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, ji->data.method);
-
- if (callee_cfg) {
- if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
- /* LLVM calls the PLT entries using bl, so emit a stub */
- emit_set_thumb_mode (acfg);
- fprintf (acfg->fp, "\n.thumb_func\n");
- emit_label (acfg, plt_entry->llvm_symbol);
- fprintf (acfg->fp, "bx pc\n");
- fprintf (acfg->fp, "nop\n");
- emit_set_arm_mode (acfg);
- fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol);
- } else {
- fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol);
- }
- continue;
- }
- }
- }
-
debug_sym = plt_entry->debug_sym;
if (acfg->thumb_mixed && !plt_entry->jit_used)
/* Emit only a thumb version */
continue;
+ /* Skip plt entries not actually called */
+ if (!plt_entry->jit_used && !plt_entry->llvm_used)
+ continue;
+
if (acfg->llvm && !acfg->thumb_mixed)
emit_label (acfg, plt_entry->llvm_symbol);
plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
ji = plt_entry->ji;
- if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer)
- continue;
-
/* Skip plt entries not actually called by LLVM code */
if (!plt_entry->llvm_used)
continue;
{
MonoMethod *method = (MonoMethod*)key;
MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
- MonoJumpInfoToken *new_ji = g_new0 (MonoJumpInfoToken, 1);
MonoAotCompile *acfg = user_data;
+ MonoJumpInfoToken *new_ji;
+ new_ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfoToken));
new_ji->image = ji->image;
new_ji->token = ji->token;
g_hash_table_insert (acfg->token_info_hash, method, new_ji);
mono_acfg_lock (acfg);
g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg);
mono_acfg_unlock (acfg);
+ g_hash_table_destroy (cfg->token_info_hash);
+ cfg->token_info_hash = NULL;
/*
* Check for absolute addresses.
return get_debug_sym (cfg->orig_method, "", llvm_acfg->method_label_hash);
}
+gboolean
+mono_aot_is_direct_callable (MonoJumpInfo *patch_info)
+{
+ return is_direct_callable (llvm_acfg, NULL, patch_info);
+}
+
+void
+mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info)
+{
+ MonoPltEntry *plt_entry;
+
+ plt_entry = get_plt_entry (llvm_acfg, patch_info);
+ plt_entry->llvm_used = FALSE;
+}
+
char*
mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
{
acfg->patch_to_got_offset_by_type [i] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
acfg->got_patches = g_ptr_array_new ();
acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
- acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+ acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, NULL);
acfg->method_to_pinvoke_import = g_hash_table_new_full (NULL, NULL, NULL, g_free);
acfg->image_hash = g_hash_table_new (NULL, NULL);
acfg->image_table = g_ptr_array_new ();
/* branches to the following block can be removed */
if (bb->last_ins && bb->last_ins->opcode == OP_BR && !bbn->out_of_line) {
- bb->last_ins->opcode = OP_NOP;
+ NULLIFY_INS (bb->last_ins);
changed = TRUE;
if (cfg->verbose_level > 2)
g_print ("br removal triggered %d -> %d\n", bb->block_num, bbn->block_num);
long_neg: dest:i src1:i len:6
long_not: dest:i src1:i len:12
long_rem: dest:i src1:i src2:i len:12
+long_rem_imm: dest:i src1:i src2:i len:12
long_rem_un: dest:i src1:i src2:i len:16
long_shl: dest:i src1:i src2:i len:14
long_shl_imm: dest:i src1:i len:14
}
#endif
MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
- ins->opcode = OP_NOP;
+ NULLIFY_INS (ins);
} else {
emulate = TRUE;
}
ins->opcode = OP_ICONST;
MONO_INST_NULLIFY_SREGS (ins);
ins->inst_c0 = 0;
+#if __s390__
+ }
+#else
} else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) {
gboolean is_long = ins->opcode == OP_LREM_IMM;
int compensator_reg = alloc_ireg (cfg);
if (power > 1) {
intermediate_reg = compensator_reg;
- MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
} else {
intermediate_reg = ins->sreg1;
}
- MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg);
/* Compute remainder */
MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1);
NULLIFY_INS (ins);
}
+#endif
break;
}
MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
case OP_LBGE:
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
case OP_LCEQ: {
int d1, d2;
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
case OP_LCLT:
MONO_START_BB (cfg, set_to_1);
MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
MONO_START_BB (cfg, set_to_0);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
default:
MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
case OP_LCEQ: {
int d1, d2;
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
case OP_LCLT:
MONO_START_BB (cfg, set_to_1);
MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
MONO_START_BB (cfg, set_to_0);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
default:
} else {
cfailed++;
- if (verbose)
- g_print ("Test '%s' failed compilation.\n", method->name);
+ g_print ("Test '%s' failed compilation.\n", method->name);
}
if (mini_stats_fd)
fprintf (mini_stats_fd, "%f, ",
/* Try dead code elimination */
if ((var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST)) && !(var->flags & MONO_INST_VOLATILE)) {
LIVENESS_DEBUG (printf ("\tdead def of R%d, eliminated\n", ins->dreg));
- ins->opcode = OP_NOP;
- ins->dreg = -1;
- MONO_INST_NULLIFY_SREGS (ins);
+ NULLIFY_INS (ins);
return;
}
(vi)->idx = (id); \
} while (0)
-void
-mono_inst_set_src_registers (MonoInst *ins, int *regs)
-{
- ins->sreg1 = regs [0];
- ins->sreg2 = regs [1];
- ins->sreg3 = regs [2];
-}
-
guint32
mono_alloc_ireg (MonoCompile *cfg)
{
ins->inst_p1 = (gpointer)(gssize)(sp [1]->inst_c0);
ins->sreg2 = -1;
- sp [1]->opcode = OP_NOP;
+ NULLIFY_INS (sp [1]);
}
}
/* Might be followed by an instruction added by ADD_WIDEN_OP */
if (sp [1]->next == NULL)
- sp [1]->opcode = OP_NOP;
+ NULLIFY_INS (sp [1]);
}
}
MONO_ADD_INS ((cfg)->cbb, (ins));
* The backends expect the fceq opcodes to do the
* comparison too.
*/
- cmp->opcode = OP_NOP;
ins->sreg1 = cmp->sreg1;
ins->sreg2 = cmp->sreg2;
+ NULLIFY_INS (cmp);
}
MONO_ADD_INS (bblock, ins);
*sp++ = ins;
guint alignment_check;
#endif
- cfg->code_size = MAX (cfg->header->code_size * 4, 10240);
+ cfg->code_size = MAX (cfg->header->code_size * 4, 1024);
#if defined(__default_codegen__)
code = cfg->native_code = g_malloc (cfg->code_size);
cfg->native_code = mono_realloc_native_code (cfg);
cfg->stat_code_reallocs++;
}
-
code = cfg->native_code + cfg->code_len;
cfg->has_unwind_info_for_epilog = TRUE;
* bblock.
*/
for (ins = bb->code; ins; ins = ins->next) {
+ gboolean modify = FALSE;
+
spec = ins_get_spec (ins->opcode);
if ((ins->dreg != -1) && (ins->dreg < max)) {
#if SIZEOF_REGISTER == 4
if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC1 + j])) {
sregs [j]++;
+ modify = TRUE;
memset (®info [sregs [j] + 1], 0, sizeof (RegTrack));
}
#endif
}
}
- mono_inst_set_src_registers (ins, sregs);
+ if (modify)
+ mono_inst_set_src_registers (ins, sregs);
}
/*if (cfg->opt & MONO_OPT_COPYPROP)
#include <mono/metadata/mempool-internals.h>
#include <mono/utils/mono-tls.h>
#include <mono/utils/mono-dl.h>
+#include <mono/utils/mono-time.h>
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
LLVMValueRef got_var;
const char *got_symbol;
GHashTable *plt_entries;
+ GHashTable *plt_entries_ji;
+ GHashTable *method_to_lmethod;
char **bb_names;
int bb_names_len;
GPtrArray *used;
switch (t->type) {
case MONO_TYPE_U1:
case MONO_TYPE_U2:
+ case MONO_TYPE_CHAR:
case MONO_TYPE_U4:
case MONO_TYPE_U8:
return TRUE;
type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
{
LLVMTypeRef ptype = type_to_llvm_type (ctx, t);
-
+
+ /*
+ * This works on all abis except arm64/ios which passes multiple
+ * arguments in one stack slot.
+ */
+#ifndef TARGET_ARM64
if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) {
/*
* LLVM generates code which only sets the lower bits, while JITted
*/
ptype = LLVMInt32Type ();
}
+#endif
return ptype;
}
{
char *callee_name = mono_aot_get_plt_symbol (type, data);
LLVMValueRef callee;
+ MonoJumpInfo *ji = NULL;
if (!callee_name)
return NULL;
g_hash_table_insert (ctx->lmodule->plt_entries, (char*)callee_name, callee);
}
+ if (ctx->cfg->compile_aot) {
+ ji = g_new0 (MonoJumpInfo, 1);
+ ji->type = type;
+ ji->data.target = data;
+
+ g_hash_table_insert (ctx->lmodule->plt_entries_ji, ji, callee);
+ }
+
return callee;
}
ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
}
} else {
- ctx->values [reg] = convert (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])));
+ ctx->values [reg] = convert_full (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])), type_is_unsigned (ctx, sig->params [i]));
}
}
/* FIXME: Free the LLVM IL for the function */
}
+ if (ctx->lmodule->method_to_lmethod)
+ g_hash_table_insert (ctx->lmodule->method_to_lmethod, cfg->method, method);
+
goto CLEANUP;
FAILURE:
aot_module.llvm_types = g_hash_table_new (NULL, NULL);
aot_module.plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
+ aot_module.plt_entries_ji = g_hash_table_new (NULL, NULL);
+ aot_module.method_to_lmethod = g_hash_table_new (NULL, NULL);
}
/*
{
LLVMTypeRef got_type;
LLVMValueRef real_got;
+ MonoLLVMModule *module = &aot_module;
/*
* Create the real got variable and replace all uses of the dummy variable with
emit_llvm_used (&aot_module);
+ /* Replace PLT entries for directly callable methods with the methods themselves */
+ {
+ GHashTableIter iter;
+ MonoJumpInfo *ji;
+ LLVMValueRef callee;
+
+ g_hash_table_iter_init (&iter, aot_module.plt_entries_ji);
+ while (g_hash_table_iter_next (&iter, (void**)&ji, (void**)&callee)) {
+ if (mono_aot_is_direct_callable (ji)) {
+ LLVMValueRef lmethod;
+
+ lmethod = g_hash_table_lookup (module->method_to_lmethod, ji->data.method);
+ /* The types might not match because the caller might pass an rgctx */
+ if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) {
+ mono_llvm_replace_uses_of (callee, lmethod);
+ mono_aot_mark_unused_llvm_plt_entry (ji);
+ }
+ }
+ }
+ }
+
#if 0
{
char *verifier_err;
gboolean
-SIG_HANDLER_SIGNATURE (mono_chain_signal)
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
{
return FALSE;
}
* was called, false otherwise.
*/
gboolean
-SIG_HANDLER_SIGNATURE (mono_chain_signal)
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
{
- int signal = _dummy;
+ int signal = MONO_SIG_HANDLER_GET_SIGNO ();
struct sigaction *saved_handler = get_saved_signal_handler (signal);
- GET_CONTEXT;
-
if (saved_handler && saved_handler->sa_handler) {
if (!(saved_handler->sa_flags & SA_SIGINFO)) {
saved_handler->sa_handler (signal);
} else {
#ifdef MONO_ARCH_USE_SIGACTION
- saved_handler->sa_sigaction (signal, info, ctx);
+ saved_handler->sa_sigaction (MONO_SIG_HANDLER_PARAMS);
#endif /* MONO_ARCH_USE_SIGACTION */
}
return TRUE;
return FALSE;
}
-SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
{
MonoJitInfo *ji = NULL;
- GET_CONTEXT;
+ MONO_SIG_HANDLER_GET_CONTEXT;
if (mono_thread_internal_current ())
- ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
+ ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
if (!ji) {
- if (mono_chain_signal (SIG_HANDLER_PARAMS))
+ if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
mono_handle_native_sigsegv (SIGABRT, ctx);
}
}
-SIG_HANDLER_FUNC (static, sigusr1_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigusr1_signal_handler)
{
gboolean running_managed;
MonoException *exc;
MonoInternalThread *thread = mono_thread_internal_current ();
MonoDomain *domain = mono_domain_get ();
void *ji;
-
- GET_CONTEXT;
+ MONO_SIG_HANDLER_GET_CONTEXT;
if (!thread || !domain) {
/* The thread might not have started up yet */
#ifdef SIGPROF
#if defined(__ia64__) || defined(__sparc__) || defined(sparc) || defined(__s390__) || defined(s390)
-SIG_HANDLER_FUNC (static, sigprof_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
{
- if (mono_chain_signal (SIG_HANDLER_PARAMS))
+ if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
NOT_IMPLEMENTED;
#else
-SIG_HANDLER_FUNC (static, sigprof_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
{
int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
- GET_CONTEXT;
+ MONO_SIG_HANDLER_GET_CONTEXT;
if (call_chain_depth == 0) {
mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
}
- mono_chain_signal (SIG_HANDLER_PARAMS);
+ mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
}
#endif
#endif
-SIG_HANDLER_FUNC (static, sigquit_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigquit_signal_handler)
{
gboolean res;
-
- GET_CONTEXT;
+ MONO_SIG_HANDLER_GET_CONTEXT;
/* We use this signal to start the attach agent too */
res = mono_attach_start ();
mono_print_thread_dump (ctx);
}
- mono_chain_signal (SIG_HANDLER_PARAMS);
+ mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
}
-SIG_HANDLER_FUNC (static, sigusr2_signal_handler)
+MONO_SIG_HANDLER_FUNC (static, sigusr2_signal_handler)
{
gboolean enabled = mono_trace_is_enabled ();
mono_trace_enable (!enabled);
- mono_chain_signal (SIG_HANDLER_PARAMS);
+ mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
}
static void
if (diff < 0)
indent_level += diff;
v = indent_level;
- printf("%p [%3d] ",pthread_self(),v);
+ printf("%p [%3d] ",(void *)pthread_self(),v);
while (v-- > 0) {
printf (". ");
}
case OP_IREM_UN_IMM:
case OP_LAND_IMM:
case OP_LOR_IMM:
+ case OP_LREM_IMM:
case OP_LXOR_IMM:
case OP_LOCALLOC_IMM:
mono_decompose_op_imm (cfg, bb, ins);
s390_lgr (code, ins->dreg, s390_r0);
break;
}
+ case OP_LREM_IMM: {
+ if (s390_is_imm16 (ins->inst_imm)) {
+ s390_lghi (code, s390_r13, ins->inst_imm);
+ } else {
+ s390_lgfi (code, s390_r13, ins->inst_imm);
+ }
+ s390_lgr (code, s390_r0, ins->sreg1);
+ s390_dsgr (code, s390_r0, s390_r13);
+ s390_lgfr (code, ins->dreg, s390_r0);
+ }
+ break;
case OP_LREM_UN: {
s390_lgr (code, s390_r1, ins->sreg1);
s390_lghi (code, s390_r0, 0);
/*------------------------------------------------------------------*/
gpointer
-mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
+mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
+ int offset, gboolean load_imt_reg)
{
- return NULL;
+ guint8 *code, *start;
+ int size = 20;
+
+ start = code = mono_global_codeman_reserve (size);
+
+ /*
+ * Replace the "this" argument with the target
+ */
+ s390_lgr (code, s390_r1, s390_r2);
+ s390_lg (code, s390_r2, s390_r1, 0, MONO_STRUCT_OFFSET(MonoDelegate, target));
+
+ /*
+ * Load the IMT register, if needed
+ */
+ if (load_imt_reg) {
+ s390_lg (code, MONO_ARCH_IMT_REG, s390_r2, 0, MONO_STRUCT_OFFSET(MonoDelegate, method));
+ }
+
+ /*
+ * Load the vTable
+ */
+ s390_lg (code, s390_r1, s390_r2, 0, MONO_STRUCT_OFFSET(MonoObject, vtable));
+ s390_agfi(code, s390_r1, offset);
+ s390_br (code, s390_r1);
+
+ return(start);
}
/*========================= End of Function ========================*/
s390_lg (code, s390_r1, 0, s390_r1, 0);
}
s390_br (code, s390_r1);
- target = S390_RELATIVE(code, item->jmp_code);
+ target = (gint64) S390_RELATIVE(code, item->jmp_code);
s390_patch_rel(item->jmp_code+2, target);
S390_SET (code, s390_r1, fail_tramp);
s390_br (code, s390_r1);
if (item->jmp_code) {
if (item->check_target_idx) {
gint64 offset;
- offset = S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
+ offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
item->jmp_code);
s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
}
{
GSList *l = NULL;
- mono_add_unwind_op_def_cfa (l, NULL, NULL, STK_BASE, 0);
+ mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
return(l);
}
* was called, false otherwise.
*/
gboolean
-SIG_HANDLER_SIGNATURE (mono_chain_signal)
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
{
MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
jit_tls->mono_win_chained_exception_needs_run = TRUE;
{
static int count = 0;
count ++;
+ static gboolean inited;
+ static const char *value;
- if (!g_getenv ("COUNT"))
+ if (!inited) {
+ value = g_getenv ("COUNT");
+ inited = TRUE;
+ }
+
+ if (!value)
return TRUE;
- if (count == atoi (g_getenv ("COUNT"))) {
+ if (count == atoi (value))
break_count ();
- }
- if (count > atoi (g_getenv ("COUNT"))) {
+ if (count > atoi (value))
return FALSE;
- }
return TRUE;
}
if ((num + 1) >= cfg->varinfo_count) {
int orig_count = cfg->varinfo_count;
- cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 64;
+ cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 32;
cfg->varinfo = (MonoInst **)g_realloc (cfg->varinfo, sizeof (MonoInst*) * cfg->varinfo_count);
cfg->vars = (MonoMethodVar *)g_realloc (cfg->vars, sizeof (MonoMethodVar) * cfg->varinfo_count);
memset (&cfg->vars [orig_count], 0, (cfg->varinfo_count - orig_count) * sizeof (MonoMethodVar));
#ifdef ENABLE_LLVM
gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0;
#endif
+ static gboolean verbose_method_inited;
+ static const char *verbose_method_name;
InterlockedIncrement (&mono_jit_stats.methods_compiled);
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
{
static gboolean inited;
- if (!inited) {
+ if (!inited)
inited = TRUE;
- }
/*
* Check for methods which cannot be compiled by LLVM early, to avoid
cfg->opt |= MONO_OPT_ABCREM;
}
- if (g_getenv ("MONO_VERBOSE_METHOD")) {
- const char *name = g_getenv ("MONO_VERBOSE_METHOD");
+ if (!verbose_method_inited) {
+ verbose_method_name = g_getenv ("MONO_VERBOSE_METHOD");
+ verbose_method_inited = TRUE;
+ }
+ if (verbose_method_name) {
+ const char *name = verbose_method_name;
if ((strchr (name, '.') > name) || strchr (name, ':')) {
MonoMethodDesc *desc;
}
mono_method_desc_free (desc);
} else {
- if (strcmp (cfg->method->name, g_getenv ("MONO_VERBOSE_METHOD")) == 0)
+ if (strcmp (cfg->method->name, name) == 0)
cfg->verbose_level = 4;
}
}
return runtime_invoke (obj, params, exc, info->compiled_method);
}
-SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
{
MonoException *exc = NULL;
MonoJitInfo *ji;
-#if !(defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32))
- void *info = NULL;
-#endif
- GET_CONTEXT;
+ void *info = MONO_SIG_HANDLER_GET_INFO ();
+ MONO_SIG_HANDLER_GET_CONTEXT;
ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
#endif
if (!ji) {
- if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+ if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
mono_handle_native_sigsegv (SIGSEGV, ctx);
if (mono_do_crash_chaining) {
- mono_chain_signal (SIG_HANDLER_PARAMS);
+ mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
return;
}
}
mono_arch_handle_exception (ctx, exc);
}
-SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
{
MonoException *exc;
- GET_CONTEXT;
+ MONO_SIG_HANDLER_GET_CONTEXT;
exc = mono_get_exception_execution_engine ("SIGILL");
#define HAVE_SIG_INFO
#endif
-SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
{
MonoJitInfo *ji;
MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
gpointer fault_addr = NULL;
-
- GET_CONTEXT;
+#ifdef HAVE_SIG_INFO
+ MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
+#endif
+ MONO_SIG_HANDLER_GET_CONTEXT;
#if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
if (mono_arch_is_single_step_event (info, ctx)) {
/* The thread might no be registered with the runtime */
if (!mono_domain_get () || !jit_tls) {
- if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+ if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
mono_handle_native_sigsegv (SIGSEGV, ctx);
if (mono_do_crash_chaining) {
- mono_chain_signal (SIG_HANDLER_PARAMS);
+ mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
return;
}
}
g_assert_not_reached ();
} else {
/* The original handler might not like that it is executed on an altstack... */
- if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
+ if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
#else
if (!ji) {
- if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+ if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
mono_handle_native_sigsegv (SIGSEGV, ctx);
if (mono_do_crash_chaining) {
- mono_chain_signal (SIG_HANDLER_PARAMS);
+ mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
return;
}
}
#endif
}
-SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
{
MonoException *exc;
- GET_CONTEXT;
+ MONO_SIG_HANDLER_GET_CONTEXT;
exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
#include <mono/utils/mono-tls.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-conc-hashtable.h>
+#include <mono/utils/mono-signal-handler.h>
#define MONO_BREAKPOINT_ARRAY_SIZE 64
#error "The code in mini/ should not depend on these defines."
#endif
-#ifndef G_LIKELY
-#define G_LIKELY(a) (a)
-#define G_UNLIKELY(a) (a)
-#endif
-
-#ifndef G_MAXINT32
-#define G_MAXINT32 2147483647
-#endif
-
-#ifndef G_MININT32
-#define G_MININT32 (-G_MAXINT32 - 1)
-#endif
-
#ifndef __GNUC__
/*#define __alignof__(a) sizeof(a)*/
#define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
#define inst_phi_args data.op[1].phi_args
#define inst_eh_block data.op[1].exception_clause
+static inline void
+mono_inst_set_src_registers (MonoInst *ins, int *regs)
+{
+ ins->sreg1 = regs [0];
+ ins->sreg2 = regs [1];
+ ins->sreg3 = regs [2];
+}
+
/* instruction description for use in regalloc/scheduling */
enum {
MONO_INST_DEST,
MONO_API char *mono_pmip (void *ip);
gboolean mono_debug_count (void) MONO_INTERNAL;
MONO_API const char* mono_inst_name (int op);
-void mono_inst_set_src_registers (MonoInst *ins, int *regs) MONO_INTERNAL;
int mono_op_to_op_imm (int opcode) MONO_INTERNAL;
int mono_op_imm_to_op (int opcode) MONO_INTERNAL;
int mono_load_membase_to_load_mem (int opcode) MONO_INTERNAL;
MonoMethod* mono_aot_get_array_helper_from_wrapper (MonoMethod *method) MONO_INTERNAL;
guint32 mono_aot_get_got_offset (MonoJumpInfo *ji) MONO_LLVM_INTERNAL;
char* mono_aot_get_method_name (MonoCompile *cfg) MONO_LLVM_INTERNAL;
+gboolean mono_aot_is_direct_callable (MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;
+void mono_aot_mark_unused_llvm_plt_entry(MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;
char* mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data) MONO_LLVM_INTERNAL;
int mono_aot_get_method_index (MonoMethod *method) MONO_LLVM_INTERNAL;
MonoJumpInfo* mono_aot_patch_info_dup (MonoJumpInfo* ji) MONO_LLVM_INTERNAL;
/*
* Signal handling
*/
-#ifdef MONO_GET_CONTEXT
-#define GET_CONTEXT MONO_GET_CONTEXT
-#endif
-
-#ifndef GET_CONTEXT
-#ifdef HOST_WIN32
-/* seh_vectored_exception_handler () passes in a CONTEXT* */
-#define GET_CONTEXT \
- void *ctx = context;
-#else
-#ifdef MONO_ARCH_USE_SIGACTION
-#define GET_CONTEXT \
- void *ctx = context;
-#elif defined(__HAIKU__)
-#define GET_CONTEXT \
- void *ctx = ®s;
-#else
-#define GET_CONTEXT \
- void **_p = (void **)&_dummy; \
- struct sigcontext *ctx = (struct sigcontext *)++_p;
-#endif
-#endif
-#endif
-
-#if defined(MONO_ARCH_USE_SIGACTION) && !defined(HOST_WIN32)
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *info, void *context))
-#define SIG_HANDLER_PARAMS _dummy, info, context
-#elif defined(HOST_WIN32)
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *info, void *context)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *info, void *context))
-#define SIG_HANDLER_PARAMS _dummy, info, context
-#elif defined(__HAIKU__)
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *userData, vregs regs)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, void *userData, vregs regs))
-#define SIG_HANDLER_PARAMS _dummy, userData, regs
-#else
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy)
-#define SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy))
-#define SIG_HANDLER_PARAMS _dummy
-#endif
-void SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) MONO_INTERNAL;
-void SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler) MONO_INTERNAL;
-void SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL;
-void SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) MONO_INTERNAL;
-gboolean SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler) MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL;
+void MONO_SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) MONO_INTERNAL;
+gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL;
#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
#define ARCH_HAVE_DELEGATE_TRAMPOLINES 1
//#define DEBUG_SSA 1
#define NEW_PHI(cfg,dest,val) do { \
- (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->opcode = OP_PHI; \
- (dest)->inst_c0 = (val); \
- (dest)->dreg = (dest)->sreg1 = (dest)->sreg2 = -1; \
+ MONO_INST_NEW ((cfg), (dest), OP_PHI); \
+ (dest)->inst_c0 = (val); \
} while (0)
typedef struct {
}
}
- ins->opcode = OP_NOP;
- ins->dreg = -1;
+ NULLIFY_INS (ins);
}
}
}
MonoInst *src_var = get_vreg_to_inst (cfg, def->sreg1);
if (src_var && !(src_var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)))
add_to_dce_worklist (cfg, info, MONO_VARINFO (cfg, src_var->inst_c0), &work_list);
- def->opcode = OP_NOP;
- def->dreg = def->sreg1 = def->sreg2 = -1;
+ NULLIFY_INS (def);
info->reg = -1;
} else if ((def->opcode == OP_ICONST) || (def->opcode == OP_I8CONST) || MONO_IS_ZERO (def)) {
- def->opcode = OP_NOP;
- def->dreg = def->sreg1 = def->sreg2 = -1;
+ NULLIFY_INS (def);
info->reg = -1;
} else if (MONO_IS_PHI (def)) {
int j;
MonoMethodVar *u = MONO_VARINFO (cfg, get_vreg_to_inst (cfg, def->inst_phi_args [j])->inst_c0);
add_to_dce_worklist (cfg, info, u, &work_list);
}
- def->opcode = OP_NOP;
- def->dreg = def->sreg1 = def->sreg2 = -1;
+ NULLIFY_INS (def);
info->reg = -1;
}
else if (def->opcode == OP_NOP) {
#define S390_SET(loc, dr, v) \
do { \
guint64 val = (guint64) v; \
- if (s390_is_uimm16(val)) { \
+ if (s390_is_imm16(val)) { \
+ s390_lghi(loc, dr, val); \
+ } else if (s390_is_uimm16(val)) { \
s390_llill(loc, dr, val); \
+ } else if (s390_is_imm32(val)) { \
+ s390_lgfi(loc, dr, val); \
} else if (s390_is_uimm32(val)) { \
s390_llilf(loc, dr, val); \
} else { \
GSList *l;
MonoUnwindOp *op;
int loc;
- guint8 *buf, *p, *res;
+ guint8 buf [4096];
+ guint8 *p, *res;
- p = buf = g_malloc0 (4096);
+ p = buf;
loc = 0;
l = unwind_ops;
*out_len = p - buf;
res = g_malloc (p - buf);
memcpy (res, buf, p - buf);
- g_free (buf);
return res;
}
export HOST_CC
endif
-if JIT_SUPPORTED
if DISABLE_EXECUTABLES
runtime_lib=../mini/$(LIBMONO_LA) $(static_libs)
else
runtime_lib=../mini/$(LIBMONO_LA)
endif
endif
-else
-runtime_lib=../interpreter/libmint.la
-endif
if DISABLE_EXECUTABLES
bin_PROGRAMS =
if !DISABLE_LIBRARIES
if !DISABLE_PROFILER
-if JIT_SUPPORTED
bin_PROGRAMS = mprof-report
lib_LTLIBRARIES = libmono-profiler-cov.la libmono-profiler-aot.la libmono-profiler-iomap.la libmono-profiler-log.la
if PLATFORM_DARWIN
endif
endif
endif
-endif
if HAVE_OPROFILE
# Do something that uses OPROFILE_CFLAGS and OPROFILE_LIBS
mono-math.c \
mono-mmap.c \
mono-mmap.h \
+ mono-mmap-internal.h \
mono-mutex.c \
mono-mutex.h \
mono-networkinterfaces.c \
MonoLockFreeAllocator *heap;
volatile Anchor anchor;
unsigned int slot_size;
+ unsigned int block_size;
unsigned int max_count;
gpointer sb;
#ifndef DESC_AVAIL_DUMMY
#define NUM_DESC_BATCH 64
-#define SB_SIZE 16384
-#define SB_HEADER_SIZE 16
-#define SB_USABLE_SIZE (SB_SIZE - SB_HEADER_SIZE)
-
-#define SB_HEADER_FOR_ADDR(a) ((gpointer)((size_t)(a) & ~(size_t)(SB_SIZE-1)))
-#define DESCRIPTOR_FOR_ADDR(a) (*(Descriptor**)SB_HEADER_FOR_ADDR (a))
+static MONO_ALWAYS_INLINE gpointer
+sb_header_for_addr (gpointer addr, size_t block_size)
+{
+ return (gpointer)(((size_t)addr) & (~(block_size - 1)));
+}
/* Taken from SGen */
return prot_flags | MONO_MMAP_PRIVATE | MONO_MMAP_ANON;
}
-static void*
-mono_sgen_alloc_os_memory (size_t size, int activate)
+static gpointer
+alloc_sb (Descriptor *desc)
{
- return mono_valloc (0, size, prot_flags_for_activate (activate));
-}
+ static int pagesize = -1;
-static void
-mono_sgen_free_os_memory (void *addr, size_t size)
-{
- mono_vfree (addr, size);
-}
+ gpointer sb_header;
-/* size must be a power of 2 */
-static void*
-mono_sgen_alloc_os_memory_aligned (size_t size, size_t alignment, gboolean activate)
-{
- return mono_valloc_aligned (size, alignment, prot_flags_for_activate (activate));
-}
+ if (pagesize == -1)
+ pagesize = mono_pagesize ();
-static gpointer
-alloc_sb (Descriptor *desc)
-{
- gpointer sb_header = mono_sgen_alloc_os_memory_aligned (SB_SIZE, SB_SIZE, TRUE);
- g_assert (sb_header == SB_HEADER_FOR_ADDR (sb_header));
- DESCRIPTOR_FOR_ADDR (sb_header) = desc;
+ sb_header = desc->block_size == pagesize ?
+ mono_valloc (0, desc->block_size, prot_flags_for_activate (TRUE)) :
+ mono_valloc_aligned (desc->block_size, desc->block_size, prot_flags_for_activate (TRUE));
+
+ g_assert (sb_header == sb_header_for_addr (sb_header, desc->block_size));
+
+ *(Descriptor**)sb_header = desc;
//g_print ("sb %p for %p\n", sb_header, desc);
- return (char*)sb_header + SB_HEADER_SIZE;
+
+ return (char*)sb_header + LOCK_FREE_ALLOC_SB_HEADER_SIZE;
}
static void
-free_sb (gpointer sb)
+free_sb (gpointer sb, size_t block_size)
{
- gpointer sb_header = SB_HEADER_FOR_ADDR (sb);
- g_assert ((char*)sb_header + SB_HEADER_SIZE == sb);
- mono_sgen_free_os_memory (sb_header, SB_SIZE);
+ gpointer sb_header = sb_header_for_addr (sb, block_size);
+ g_assert ((char*)sb_header + LOCK_FREE_ALLOC_SB_HEADER_SIZE == sb);
+ mono_vfree (sb_header, block_size);
//g_print ("free sb %p\n", sb_header);
}
Descriptor *d;
int i;
- desc = mono_sgen_alloc_os_memory (desc_size * NUM_DESC_BATCH, TRUE);
+ desc = mono_valloc (0, desc_size * NUM_DESC_BATCH, prot_flags_for_activate (TRUE));
/* Organize into linked list. */
d = desc;
success = (InterlockedCompareExchangePointer ((gpointer * volatile)&desc_avail, desc->next, NULL) == NULL);
if (!success)
- mono_sgen_free_os_memory (desc, desc_size * NUM_DESC_BATCH);
+ mono_vfree (desc, desc_size * NUM_DESC_BATCH);
}
mono_hazard_pointer_clear (hp, 1);
g_assert (desc->anchor.data.state == STATE_EMPTY);
g_assert (desc->in_use);
desc->in_use = FALSE;
- free_sb (desc->sb);
+ free_sb (desc->sb, desc->block_size);
mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, FALSE, TRUE);
}
#else
static void
desc_retire (Descriptor *desc)
{
- free_sb (desc->sb);
+ free_sb (desc->sb, desc->block_size);
mono_lock_free_queue_enqueue (&available_descs, &desc->node);
}
#endif
mono_memory_read_barrier ();
next = *(unsigned int*)addr;
- g_assert (next < SB_USABLE_SIZE / desc->slot_size);
+ g_assert (next < LOCK_FREE_ALLOC_SB_USABLE_SIZE (desc->block_size) / desc->slot_size);
new_anchor.data.avail = next;
--new_anchor.data.count;
static gpointer
alloc_from_new_sb (MonoLockFreeAllocator *heap)
{
- unsigned int slot_size, count, i;
+ unsigned int slot_size, block_size, count, i;
Descriptor *desc = desc_alloc ();
- desc->sb = alloc_sb (desc);
-
slot_size = desc->slot_size = heap->sc->slot_size;
- count = SB_USABLE_SIZE / slot_size;
-
- /* Organize blocks into linked list. */
- for (i = 1; i < count - 1; ++i)
- *(unsigned int*)((char*)desc->sb + i * slot_size) = i + 1;
+ block_size = desc->block_size = heap->sc->block_size;
+ count = LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size) / slot_size;
desc->heap = heap;
/*
desc->anchor.data.count = desc->max_count - 1;
desc->anchor.data.state = STATE_PARTIAL;
+ desc->sb = alloc_sb (desc);
+
+ /* Organize blocks into linked list. */
+ for (i = 1; i < count - 1; ++i)
+ *(unsigned int*)((char*)desc->sb + i * slot_size) = i + 1;
+
mono_memory_write_barrier ();
/* Make it active or free it again. */
}
void
-mono_lock_free_free (gpointer ptr)
+mono_lock_free_free (gpointer ptr, size_t block_size)
{
Anchor old_anchor, new_anchor;
Descriptor *desc;
gpointer sb;
MonoLockFreeAllocator *heap = NULL;
- desc = DESCRIPTOR_FOR_ADDR (ptr);
+ desc = *(Descriptor**) sb_header_for_addr (ptr, block_size);
+ g_assert (block_size == desc->block_size);
+
sb = desc->sb;
- g_assert (SB_HEADER_FOR_ADDR (ptr) == SB_HEADER_FOR_ADDR (sb));
do {
new_anchor = old_anchor = *(volatile Anchor*)&desc->anchor.value;
*(unsigned int*)ptr = old_anchor.data.avail;
new_anchor.data.avail = ((char*)ptr - (char*)sb) / desc->slot_size;
- g_assert (new_anchor.data.avail < SB_USABLE_SIZE / desc->slot_size);
+ g_assert (new_anchor.data.avail < LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size) / desc->slot_size);
if (old_anchor.data.state == STATE_FULL)
new_anchor.data.state = STATE_PARTIAL;
descriptor_check_consistency (Descriptor *desc, gboolean print)
{
int count = desc->anchor.data.count;
- int max_count = SB_USABLE_SIZE / desc->slot_size;
+ int max_count = LOCK_FREE_ALLOC_SB_USABLE_SIZE (desc->block_size) / desc->slot_size;
#if _MSC_VER
gboolean* linked = alloca(max_count*sizeof(gboolean));
#else
}
void
-mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size)
+mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size, unsigned int block_size)
{
- g_assert (slot_size <= SB_USABLE_SIZE / 2);
+ g_assert (block_size > 0);
+ g_assert ((block_size & (block_size - 1)) == 0); /* check if power of 2 */
+ g_assert (slot_size * 2 <= LOCK_FREE_ALLOC_SB_USABLE_SIZE (block_size));
mono_lock_free_queue_init (&sc->partial);
sc->slot_size = slot_size;
+ sc->block_size = block_size;
}
void
typedef struct {
MonoLockFreeQueue partial;
unsigned int slot_size;
+ unsigned int block_size;
} MonoLockFreeAllocSizeClass;
struct _MonoLockFreeAllocDescriptor;
MonoLockFreeAllocSizeClass *sc;
} MonoLockFreeAllocator;
-void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size) MONO_INTERNAL;
+#define LOCK_FREE_ALLOC_SB_MAX_SIZE 16384
+#define LOCK_FREE_ALLOC_SB_HEADER_SIZE (sizeof (MonoLockFreeAllocator))
+#define LOCK_FREE_ALLOC_SB_USABLE_SIZE(block_size) ((block_size) - LOCK_FREE_ALLOC_SB_HEADER_SIZE)
+
+void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size, unsigned int block_size) MONO_INTERNAL;
void mono_lock_free_allocator_init_allocator (MonoLockFreeAllocator *heap, MonoLockFreeAllocSizeClass *sc) MONO_INTERNAL;
gpointer mono_lock_free_alloc (MonoLockFreeAllocator *heap) MONO_INTERNAL;
-void mono_lock_free_free (gpointer ptr) MONO_INTERNAL;
+void mono_lock_free_free (gpointer ptr, size_t block_size) MONO_INTERNAL;
gboolean mono_lock_free_allocator_check_consistency (MonoLockFreeAllocator *heap) MONO_INTERNAL;
--- /dev/null
+/*
+ * mono-mmap-internal.h: Internal virtual memory stuff.
+ *
+ * Copyright (C) 2014 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MONO_UTILS_MMAP_INTERNAL_H__
+#define __MONO_UTILS_MMAP_INTERNAL_H__
+
+#include "mono-compiler.h"
+
+int mono_pages_not_faulted (void *addr, size_t length) MONO_INTERNAL;
+
+#endif /* __MONO_UTILS_MMAP_INTERNAL_H__ */
+
#endif
#include "mono-mmap.h"
+#include "mono-mmap-internal.h"
#include "mono-proclib.h"
#ifndef MAP_ANONYMOUS
return 0;
}
+int
+mono_pages_not_faulted (void *addr, size_t length)
+{
+ return -1;
+}
+
#else
#if defined(HAVE_MMAP)
}
#endif // __native_client__
+int
+mono_pages_not_faulted (void *addr, size_t size)
+{
+ int i;
+ gint64 count;
+ int pagesize = mono_pagesize ();
+ int npages = (size + pagesize - 1) / pagesize;
+ char *faulted = g_malloc0 (sizeof (char*) * npages);
+
+ if (mincore (addr, size, faulted) != 0) {
+ count = -1;
+ } else {
+ count = 0;
+ for (i = 0; i < npages; ++i) {
+ if (faulted [i] != 0)
+ ++count;
+ }
+ }
+
+ g_free (faulted);
+
+ return count;
+}
+
#else
/* dummy malloc-based implementation */
}
return 0;
}
+
+int
+mono_pages_not_faulted (void *addr, size_t length)
+{
+ return -1;
+}
+
#endif // HAVE_MMAP
#if defined(HAVE_SHM_OPEN) && !defined (DISABLE_SHARED_PERFCOUNTERS)
#ifdef ENABLE_EXTENSION_MODULE
#include "../../../mono-extensions/mono/utils/mono-signal-handler.h"
#endif
-/*
-Not all platforms support signal handlers in the same way. Some have the same concept but
-for some weird reason pass different kind of arguments.
-
-All signal handler helpers should go here so they can be properly shared across the JIT,
-utils and sgen.
-
-TODO: Cleanup & move mini's macros to here so they can leveraged by other parts.
-*/
+/* Don't use this */
#ifndef MONO_SIGNAL_HANDLER_FUNC
#define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) access void name arglist
#endif
+/*
+ * Macros to work around signal handler differences on various platforms.
+ *
+ * To declare a signal handler function:
+ * void MONO_SIG_HANDLER_SIGNATURE (handler_func)
+ * To define a signal handler function:
+ * MONO_SIG_HANDLER_FUNC(access, name)
+ * To call another signal handler function:
+ * handler_func (MONO_SIG_HANDLER_PARAMS);
+ * To obtain the signal number:
+ * int signo = MONO_SIG_HANDLER_GET_SIGNO ();
+ * To obtain the signal context:
+ * MONO_SIG_HANDLER_GET_CONTEXT ().
+ * This will define a variable name 'ctx'.
+ */
+
+#ifdef HOST_WIN32
+#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *_info, void *context)
+#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *_info, void *context))
+#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context
+#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy)
+#define MONO_SIG_HANDLER_GET_INFO() (_info)
+#define MONO_SIG_HANDLER_INFO_TYPE EXCEPTION_POINTERS
+/* seh_vectored_exception_handler () passes in a CONTEXT* */
+#define MONO_SIG_HANDLER_GET_CONTEXT \
+ void *ctx = context;
+#else
+/* sigaction */
+#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *_info, void *context)
+#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *_info, void *context))
+#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context
+#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy)
+#define MONO_SIG_HANDLER_GET_INFO() (_info)
+#define MONO_SIG_HANDLER_INFO_TYPE siginfo_t
+#define MONO_SIG_HANDLER_GET_CONTEXT \
+ void *ctx = context;
+#endif
+
#endif
get-cygwin-deps.sh \
mono-configuration-crypto.in
-if USE_JIT
mono_interp = mono
-else
-mono_interp = mint
-endif
if HOST_WIN32
if CROSS_COMPILING